├── cv2 ├── __init__.py └── data │ └── __init__.py ├── tests ├── get_build_info.py ├── SampleVideo_1280x720_1mb.mp4 ├── test.py └── pylintrc ├── travis_multibuild_customize.sh ├── MANIFEST.in ├── .gitmodules ├── docker ├── README.md ├── manylinux1 │ ├── Dockerfile_x86_64 │ └── Dockerfile_i686 ├── manylinux2014 │ ├── Dockerfile_i686 │ ├── Dockerfile_x86_64 │ └── Dockerfile_aarch64 ├── musllinux_1_2 │ ├── Dockerfile_x86_64 │ └── Dockerfile_aarch64 └── manylinux_2_28 │ ├── Dockerfile_aarch64 │ └── Dockerfile_x86_64 ├── patch_auditwheel_whitelist.py ├── pyproject.toml ├── scripts ├── build.sh ├── install.sh └── __init__.py ├── _build_backend └── backend.py ├── LICENSE.txt ├── patches ├── patchQtPlugins └── patchOpenEXR ├── .gitignore ├── CONTRIBUTING.md ├── .github ├── issue_template.md └── workflows │ ├── build_wheels_macos_m1.yml │ ├── build_wheels_windows.yml │ ├── build_wheels_macos.yml │ └── build_wheels_manylinux.yml ├── find_version.py ├── travis_config.sh ├── README.md ├── travis_osx_brew_cache.sh └── setup.py /cv2/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/get_build_info.py: -------------------------------------------------------------------------------- 1 | import cv2 as cv 2 | 3 | print(cv.getBuildInformation()) 4 | -------------------------------------------------------------------------------- /cv2/data/__init__.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | haarcascades = os.path.join(os.path.dirname(__file__), "") 4 | -------------------------------------------------------------------------------- /tests/SampleVideo_1280x720_1mb.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/opencv/opencv-python/HEAD/tests/SampleVideo_1280x720_1mb.mp4 -------------------------------------------------------------------------------- /travis_multibuild_customize.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Customize multibuild logic that is run before entering Docker. Sourced from travis.yml . 3 | export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' 4 | set -x 5 | REPO_DIR=$(dirname "${BASH_SOURCE[0]}") 6 | DOCKER_IMAGE='quay.io/asenyaev/manylinux2014_$plat' 7 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE-3RD-PARTY.txt 2 | include LICENSE.txt 3 | include README.md 4 | include find_version.py 5 | include setup.py 6 | include pyproject.toml 7 | include _build_backend/backend.py 8 | recursive-include cv2 * 9 | recursive-include docker * 10 | recursive-include opencv * 11 | recursive-include opencv_contrib * 12 | recursive-include patches * 13 | recursive-include scripts *.py 14 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "opencv"] 2 | path = opencv 3 | url = https://github.com/opencv/opencv.git 4 | [submodule "opencv_contrib"] 5 | path = opencv_contrib 6 | url = https://github.com/opencv/opencv_contrib.git 7 | [submodule "multibuild"] 8 | path = multibuild 9 | url = https://github.com/multi-build/multibuild.git 10 | [submodule "opencv_extra"] 11 | path = opencv_extra 12 | url = https://github.com/opencv/opencv_extra.git 13 | -------------------------------------------------------------------------------- /tests/test.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import sys 3 | 4 | 5 | class OpenCVTest(unittest.TestCase): 6 | """ Simple functionality tests. """ 7 | 8 | def test_import(self): 9 | """ Test that the cv2 module can be imported. """ 10 | import cv2 11 | 12 | def test_video_capture(self): 13 | 14 | import cv2 15 | 16 | cap = cv2.VideoCapture("SampleVideo_1280x720_1mb.mp4") 17 | self.assertTrue(cap.isOpened()) 18 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | ### Customized manylinux images for opencv-python 2 | 3 | The subfolders include Dockerfiles for extending both ``i686`` and ``x86_64`` manylinux1 and manylinux2014 images. 4 | 5 | Manylinux2014 is used in wheels with version 3.4.10.* / 4.3.0.* and above. 6 | 7 | The extended images were created to be able to build OpenCV in reasonable time with Travis. The images are hosted at https://quay.io/user/skvark. 8 | 9 | See the dockerfiles for more info. 10 | -------------------------------------------------------------------------------- /tests/pylintrc: -------------------------------------------------------------------------------- 1 | # Source: opencv/platforms/scripts/pylintrc 2 | 3 | [MESSAGES CONTROL] 4 | 5 | # Disable all to choose the Tests one by one 6 | disable=all 7 | 8 | # Tests 9 | enable=bad-indentation, # Used when an unexpected number of indentation’s tabulations or spaces has been found. 10 | mixed-indentation, # Used when there are some mixed tabs and spaces in a module. 11 | unnecessary-semicolon, # Used when a statement is ended by a semi-colon (”;”), which isn’t necessary. 12 | unused-variable # Used when a variable is defined but not used. (Use _var to ignore var). 13 | -------------------------------------------------------------------------------- /patch_auditwheel_whitelist.py: -------------------------------------------------------------------------------- 1 | from os.path import join, dirname, abspath 2 | import json 3 | 4 | from auditwheel import policy 5 | 6 | def add_whitelisted_libs(): 7 | policies = None 8 | 9 | with open(join(dirname(abspath(policy.__file__)), "manylinux-policy.json")) as f: 10 | policies = json.load(f) 11 | 12 | for p in policies: 13 | p["lib_whitelist"].append("libxcb.so.1") 14 | 15 | with open(join(dirname(abspath(policy.__file__)), "manylinux-policy.json"), "w") as f: 16 | f.write(json.dumps(policies)) 17 | 18 | if __name__ == '__main__': 19 | add_whitelisted_libs() 20 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "numpy<2.0; python_version<'3.9'", 4 | "numpy==2.0.2; python_version>='3.9' and python_version<'3.13'", 5 | "numpy==2.1.3; python_version=='3.13'", 6 | "packaging", 7 | "pip", 8 | "scikit-build>=0.14.0", 9 | "setuptools==59.2.0; python_version<'3.12'", 10 | "setuptools<70.0.0; python_version>='3.12'", 11 | ] 12 | # use a custom backend to manage CMake check / installation 13 | # see https://scikit-build.readthedocs.io/en/latest/usage.html#adding-cmake-as-building-requirement-only-if-not-installed-or-too-low-a-version 14 | build-backend = "backend" 15 | backend-path = ["_build_backend"] 16 | -------------------------------------------------------------------------------- /scripts/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | # Check out and prepare the source 5 | # Multibuild doesn't have releases, so --depth would break eventually (see 6 | # https://superuser.com/questions/1240216/server-does-not-allow-request-for-unadvertised) 7 | git submodule update --init multibuild 8 | source multibuild/common_utils.sh 9 | # https://github.com/matthew-brett/multibuild/issues/116 10 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export ARCH_FLAGS=" "; fi 11 | source multibuild/travis_steps.sh 12 | # This sets -x 13 | # source travis_multibuild_customize.sh 14 | echo $ENABLE_CONTRIB > contrib.enabled 15 | echo $ENABLE_HEADLESS > headless.enabled 16 | echo $ENABLE_ROLLING > rolling.enabled 17 | set -x 18 | build_wheel $REPO_DIR $PLAT 19 | -------------------------------------------------------------------------------- /scripts/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | # Check out and prepare the source 5 | # Multibuild doesn't have releases, so --depth would break eventually (see 6 | # https://superuser.com/questions/1240216/server-does-not-allow-request-for-unadvertised) 7 | git submodule update --init --recursive 8 | source multibuild/common_utils.sh 9 | # https://github.com/matthew-brett/multibuild/issues/116 10 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export ARCH_FLAGS=" "; fi 11 | source multibuild/travis_steps.sh 12 | # This sets -x 13 | # source travis_multibuild_customize.sh 14 | echo $ENABLE_CONTRIB > contrib.enabled 15 | echo $ENABLE_HEADLESS > headless.enabled 16 | echo $ENABLE_ROLLING > rolling.enabled 17 | set -x 18 | install_run $PLAT 19 | set +x 20 | -------------------------------------------------------------------------------- /scripts/__init__.py: -------------------------------------------------------------------------------- 1 | PYTHON_EXTENSIONS_PATHS = [ 2 | LOADER_DIR 3 | ] + PYTHON_EXTENSIONS_PATHS 4 | 5 | ci_and_not_headless = False 6 | 7 | try: 8 | from .version import ci_build, headless 9 | 10 | ci_and_not_headless = ci_build and not headless 11 | except: 12 | pass 13 | 14 | # the Qt plugin is included currently only in the pre-built wheels 15 | if sys.platform.startswith("linux") and ci_and_not_headless: 16 | os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = os.path.join( 17 | os.path.dirname(os.path.abspath(__file__)), "qt", "plugins" 18 | ) 19 | 20 | # Qt will throw warning on Linux if fonts are not found 21 | if sys.platform.startswith("linux") and ci_and_not_headless: 22 | os.environ["QT_QPA_FONTDIR"] = os.path.join( 23 | os.path.dirname(os.path.abspath(__file__)), "qt", "fonts" 24 | ) 25 | -------------------------------------------------------------------------------- /_build_backend/backend.py: -------------------------------------------------------------------------------- 1 | from setuptools import build_meta as _orig 2 | 3 | prepare_metadata_for_build_wheel = _orig.prepare_metadata_for_build_wheel 4 | build_wheel = _orig.build_wheel 5 | build_sdist = _orig.build_sdist 6 | get_requires_for_build_sdist = _orig.get_requires_for_build_sdist 7 | 8 | def get_requires_for_build_wheel(config_settings=None): 9 | from packaging import version 10 | from skbuild.exceptions import SKBuildError 11 | from skbuild.cmaker import get_cmake_version 12 | packages = _orig.get_requires_for_build_wheel(config_settings) 13 | # check if system cmake can be used if present 14 | # if not, append cmake PyPI distribution to required packages 15 | # scikit-build>=0.18 itself requires cmake 3.5+ 16 | min_version = "3.5" 17 | try: 18 | if version.parse(get_cmake_version().split("-")[0]) < version.parse(min_version): 19 | packages.append(f'cmake>={min_version}') 20 | except SKBuildError: 21 | packages.append(f'cmake>={min_version}') 22 | 23 | return packages 24 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Olli-Pekka Heinisuo 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /patches/patchQtPlugins: -------------------------------------------------------------------------------- 1 | diff --git a/opencv/CMakeLists.txt b/opencv/CMakeLists.txt 2 | index 4c0b3880fc..dffa0a4caa 100644 3 | --- a/opencv/CMakeLists.txt 4 | +++ b/opencv/CMakeLists.txt 5 | @@ -1187,6 +1187,13 @@ if(WITH_QT OR HAVE_QT) 6 | if(HAVE_QT) 7 | status(" QT:" "YES (ver ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}.${QT_VERSION_PATCH} ${QT_EDITION})") 8 | + if(APPLE) 9 | + install(DIRECTORY ${Qt5_DIR}/../../../plugins DESTINATION lib/qt) 10 | + endif() 11 | + if(UNIX AND NOT APPLE) 12 | + install(DIRECTORY /opt/Qt5.15.16/plugins DESTINATION lib/qt) 13 | + install(DIRECTORY /usr/share/fonts DESTINATION lib/qt) 14 | + endif() 15 | if(HAVE_QT_OPENGL) 16 | if(Qt${QT_VERSION_MAJOR}OpenGL_LIBRARIES) 17 | status(" QT OpenGL support:" HAVE_QT_OPENGL THEN "YES (${Qt${QT_VERSION_MAJOR}OpenGL_LIBRARIES} ${Qt${QT_VERSION_MAJOR}OpenGL_VERSION_STRING})" ELSE NO) 18 | else() 19 | status(" QT OpenGL support:" HAVE_QT_OPENGL THEN "YES (${QT_QTOPENGL_LIBRARY})" ELSE NO) 20 | endif() 21 | else() 22 | status(" QT OpenGL support:" "NO") 23 | endif() 24 | else() 25 | status(" QT:" "NO") 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | #Ipython Notebook 62 | .ipynb_checkpoints 63 | 64 | #PyCharm 65 | /.idea 66 | 67 | # Build temporary files 68 | /contrib.enabled 69 | /cv_version.py 70 | /cv2/version.py 71 | _skbuild/ 72 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributing 2 | 3 | Thank you for considering contributing to opencv-python. 4 | 5 | ### 1. Where do I go from here? 6 | 7 | If you've noticed a bug or have a question that doesn't belong on 8 | [Stack Overflow](http://stackoverflow.com/questions/tagged/opencv-python), 9 | [search the project issue tracker](https://github.com/opencv/opencv-python/issues?q=something) or 10 | [search OpenCV issue tracker](https://github.com/opencv/opencv/issues?q=is%3Aissue+is%3Aopen+label%3A%22category%3A+python+bindings%22) 11 | to see if someone else in the community has already created a ticket. 12 | If not, go ahead and: 13 | - [make new one for opencv-python](https://github.com/opencv/opencv-python/issues/new) if you cannot load package or some functionality is not available! 14 | - [make new one for OpenCV](https://github.com/opencv/opencv-python/issues/new) if something went wrong with some function, class or method in code! 15 | 16 | ### 2. Fork & create a branch 17 | 18 | If this is something you think you can fix, then 19 | [fork opencv-python](https://help.github.com/articles/fork-a-repo) 20 | and create a branch with a descriptive name. 21 | 22 | ### 3. Make your changes 23 | 24 | Make required changes. 25 | 26 | ### 4. Create a pull request 27 | 28 | [Make a Pull Request.](https://help.github.com/articles/creating-a-pull-request) 29 | -------------------------------------------------------------------------------- /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ### Expected behaviour 2 | 3 | Write here how did you expect the library to function. 4 | 5 | ### Actual behaviour 6 | 7 | Write here what went wrong. 8 | 9 | ### Steps to reproduce 10 | 11 | - example code 12 | - operating system 13 | - architecture (e.g. x86) 14 | - opencv-python version 15 | 16 | ##### Issue submission checklist 17 | 18 | - [ ] This is not a generic OpenCV usage question (looking for help for coding, other usage questions, homework etc.) 19 | 25 | - [ ] I have read the README of this repository and understand that this repository provides only an automated build toolchain for OpenCV Python packages (there is no actual OpenCV code here) 26 | 41 | - [ ] The issue is related to the build scripts in this repository, to the pre-built binaries or is a feature request (such as "please enable this additional dependency") 42 | - [ ] I'm using the latest version of ``opencv-python`` 43 | -------------------------------------------------------------------------------- /patches/patchOpenEXR: -------------------------------------------------------------------------------- 1 | diff -ruN opencv/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp opencv_patched/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp 2 | --- opencv/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp 2019-08-25 10:40:57.596395000 -0400 3 | +++ opencv_patched/3rdparty/openexr/IlmImf/ImfSystemSpecific.cpp 2019-08-25 10:53:15.331689900 -0400 4 | @@ -40,21 +40,19 @@ 5 | 6 | namespace { 7 | #if defined(IMF_HAVE_SSE2) && defined(__GNUC__) && !defined(__ANDROID__) 8 | - 9 | +#include 10 | // Helper functions for gcc + SSE enabled 11 | - void cpuid(int n, int &eax, int &ebx, int &ecx, int &edx) 12 | + void cpuid(unsigned int n, unsigned int &eax, unsigned int &ebx, 13 | + unsigned int &ecx, unsigned int &edx) 14 | { 15 | - __asm__ __volatile__ ( 16 | - "cpuid" 17 | - : /* Output */ "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) 18 | - : /* Input */ "a"(n) 19 | - : /* Clobber */); 20 | + __get_cpuid(n, &eax, &ebx, &ecx, &edx); 21 | } 22 | 23 | #else // IMF_HAVE_SSE2 && __GNUC__ 24 | 25 | // Helper functions for generic compiler - all disabled 26 | - void cpuid(int n, int &eax, int &ebx, int &ecx, int &edx) 27 | + void cpuid(unsigned int n, unsigned int &eax, unsigned int &ebx, 28 | + unsigned int &ecx, unsigned int &edx) 29 | { 30 | eax = ebx = ecx = edx = 0; 31 | } 32 | @@ -64,7 +62,7 @@ 33 | 34 | #ifdef OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX 35 | 36 | - void xgetbv(int n, int &eax, int &edx) 37 | + void xgetbv(unsigned int n, unsigned int &eax, unsigned int &edx) 38 | { 39 | __asm__ __volatile__ ( 40 | "xgetbv" 41 | @@ -75,7 +73,7 @@ 42 | 43 | #else // OPENEXR_IMF_HAVE_GCC_INLINE_ASM_AVX 44 | 45 | - void xgetbv(int n, int &eax, int &edx) 46 | + void xgetbv(unsigned int n, unsigned int &eax, unsigned int &edx) 47 | { 48 | eax = edx = 0; 49 | } 50 | @@ -94,8 +92,8 @@ 51 | f16c(false) 52 | { 53 | bool osxsave = false; 54 | - int max = 0; 55 | - int eax, ebx, ecx, edx; 56 | + unsigned int max = 0; 57 | + unsigned int eax, ebx, ecx, edx; 58 | 59 | cpuid(0, max, ebx, ecx, edx); 60 | if (max > 0) 61 | -------------------------------------------------------------------------------- /find_version.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import subprocess 3 | from datetime import date 4 | 5 | if __name__ == "__main__": 6 | contrib = sys.argv[1] 7 | headless = sys.argv[2] 8 | rolling = sys.argv[3] 9 | ci_build = sys.argv[4] 10 | 11 | opencv_version = "" 12 | # dig out the version from OpenCV sources 13 | version_file_path = "opencv/modules/core/include/opencv2/core/version.hpp" 14 | 15 | with open(version_file_path, "r") as f: 16 | for line in f: 17 | words = line.split() 18 | 19 | if "CV_VERSION_MAJOR" in words: 20 | opencv_version += words[2] 21 | opencv_version += "." 22 | 23 | if "CV_VERSION_MINOR" in words: 24 | opencv_version += words[2] 25 | opencv_version += "." 26 | 27 | if "CV_VERSION_REVISION" in words: 28 | opencv_version += words[2] 29 | break 30 | 31 | # used in local dev releases 32 | git_hash = ( 33 | subprocess.check_output(["git", "rev-parse", "--short", "HEAD"]) 34 | .splitlines()[0] 35 | .decode() 36 | ) 37 | # this outputs the annotated tag if we are exactly on a tag, otherwise --g 38 | try: 39 | tag = ( 40 | subprocess.check_output( 41 | ["git", "describe", "--tags"], stderr=subprocess.STDOUT 42 | ) 43 | .splitlines()[0] 44 | .decode() 45 | .split("-") 46 | ) 47 | except subprocess.CalledProcessError as e: 48 | # no tags reachable (e.g. on a topic branch in a fork), see 49 | # https://stackoverflow.com/questions/4916492/git-describe-fails-with-fatal-no-names-found-cannot-describe-anything 50 | if e.output.rstrip() == b"fatal: No names found, cannot describe anything.": 51 | tag = [] 52 | else: 53 | print(e.output) 54 | raise 55 | 56 | if len(tag) == 1: 57 | # tag identifies the build and should be a sequential revision number 58 | version = tag[0] 59 | opencv_version += ".{}".format(version) 60 | # rolling has converted into string using get_and_set_info() function in setup.py 61 | elif rolling == "True": 62 | # rolling version identifier, will be published in a dedicated rolling PyPI repository 63 | version = date.today().strftime('%Y%m%d') 64 | opencv_version += ".{}".format(version) 65 | else: 66 | # local version identifier, not to be published on PyPI 67 | version = git_hash 68 | opencv_version += "+{}".format(version) 69 | 70 | with open("cv2/version.py", "w") as f: 71 | f.write('opencv_version = "{}"\n'.format(opencv_version)) 72 | f.write("contrib = {}\n".format(contrib)) 73 | f.write("headless = {}\n".format(headless)) 74 | f.write("rolling = {}\n".format(rolling)) 75 | f.write("ci_build = {}".format(ci_build)) 76 | -------------------------------------------------------------------------------- /docker/manylinux1/Dockerfile_x86_64: -------------------------------------------------------------------------------- 1 | FROM quay.io/pypa/manylinux1_x86_64:latest 2 | 3 | RUN curl -O -L https://download.qt.io/archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.tar.gz && \ 4 | tar -xf qt-everywhere-opensource-src-4.8.7.tar.gz && \ 5 | cd qt-everywhere* && \ 6 | #configure does a bootstrap make under the hood 7 | #manylinux1 is too old to have `nproc` 8 | export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN) && \ 9 | #OpenCV only links against QtCore, QtGui, QtTest 10 | ./configure -prefix /opt/Qt4.8.7 -release -opensource -confirm-license \ 11 | -no-sql-sqlite -no-qt3support -no-xmlpatterns -no-multimedia \ 12 | -no-webkit -no-script -no-declarative -no-dbus -make libs && \ 13 | make && \ 14 | make install && \ 15 | cd .. && \ 16 | rm -rf qt-everywhere-opensource-src-4.8.7 && \ 17 | rm qt-everywhere-opensource-src-4.8.7.tar.gz 18 | 19 | ENV QTDIR /opt/Qt4.8.7 20 | ENV PATH "$QTDIR/bin:$PATH" 21 | 22 | RUN curl -O -L https://cmake.org/files/v3.9/cmake-3.9.0.tar.gz && \ 23 | tar -xf cmake-3.9.0.tar.gz && \ 24 | cd cmake-3.9.0 && \ 25 | #manylinux1 provides curl-devel equivalent and libcurl statically linked 26 | # against the same newer OpenSSL as other source-built tools 27 | # (1.0.2s as of this writing) 28 | yum -y install zlib-devel && \ 29 | #configure does a bootstrap make under the hood 30 | export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN) && \ 31 | ./configure --system-curl && \ 32 | make && \ 33 | make install && \ 34 | cd .. && \ 35 | rm -rf cmake-3.9.0* 36 | 37 | # https://trac.ffmpeg.org/wiki/CompilationGuide/Centos#GettheDependencies 38 | # manylinux provides the toolchain and git; we provide cmake 39 | RUN yum install freetype-devel bzip2-devel zlib-devel -y && \ 40 | mkdir ~/ffmpeg_sources 41 | 42 | # Newer openssl configure requires newer perl 43 | RUN curl -O -L https://www.cpan.org/src/5.0/perl-5.20.1.tar.gz && \ 44 | tar -xf perl-5.20.1.tar.gz && \ 45 | cd perl-5.20.1 && \ 46 | ./Configure -des -Dprefix="$HOME/openssl_build" && \ 47 | #perl build scripts do much redundant work 48 | # if running "make install" separately 49 | make install -j$(getconf _NPROCESSORS_ONLN) && \ 50 | cd .. && \ 51 | rm -rf perl-5.20.1* 52 | 53 | RUN cd ~/ffmpeg_sources && \ 54 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_1_1_1c.tar.gz && \ 55 | tar -xf OpenSSL_1_1_1c.tar.gz && \ 56 | cd openssl-OpenSSL_1_1_1c && \ 57 | PERL="$HOME/openssl_build/bin/perl" ./config --prefix="$HOME/ffmpeg_build" --openssldir="$HOME/ffmpeg_build" shared zlib && \ 58 | make -j$(getconf _NPROCESSORS_ONLN) && \ 59 | #skip installing documentation 60 | make install_sw && \ 61 | rm -rf ~/openssl_build 62 | 63 | RUN cd ~/ffmpeg_sources && \ 64 | curl -O -L http://www.nasm.us/pub/nasm/releasebuilds/2.14.01/nasm-2.14.01.tar.bz2 && \ 65 | tar -xf nasm-2.14.01.tar.bz2 && cd nasm-2.14.01 && ./autogen.sh && \ 66 | ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \ 67 | make -j$(getconf _NPROCESSORS_ONLN) && \ 68 | make install 69 | 70 | RUN cd ~/ffmpeg_sources && \ 71 | curl -O -L http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz && \ 72 | tar -xf yasm-1.3.0.tar.gz && \ 73 | cd yasm-1.3.0 && \ 74 | ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \ 75 | make -j$(getconf _NPROCESSORS_ONLN) && \ 76 | make install 77 | 78 | RUN cd ~/ffmpeg_sources && \ 79 | git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git && \ 80 | cd libvpx && \ 81 | ./configure --prefix="$HOME/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 82 | make -j$(getconf _NPROCESSORS_ONLN) && \ 83 | make install 84 | 85 | RUN cd ~/ffmpeg_sources && \ 86 | curl -O -L https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && \ 87 | tar -xf ffmpeg-snapshot.tar.bz2 && \ 88 | cd ffmpeg && \ 89 | PATH=~/bin:$PATH && \ 90 | PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 91 | make -j$(getconf _NPROCESSORS_ONLN) && \ 92 | make install && \ 93 | echo "/root/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 94 | ldconfig && \ 95 | rm -rf ~/ffmpeg_sources 96 | 97 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/root/ffmpeg_build/lib/pkgconfig 98 | ENV LDFLAGS -L/root/ffmpeg_build/lib 99 | 100 | RUN curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/uapi/linux/videodev2.h && \ 101 | curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/uapi/linux/v4l2-common.h && \ 102 | curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/uapi/linux/v4l2-controls.h && \ 103 | curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/linux/compiler.h && \ 104 | mv videodev2.h v4l2-common.h v4l2-controls.h compiler.h /usr/include/linux 105 | 106 | ENV PATH "$HOME/bin:$PATH" 107 | -------------------------------------------------------------------------------- /docker/manylinux2014/Dockerfile_i686: -------------------------------------------------------------------------------- 1 | FROM quay.io/pypa/manylinux2014_i686:latest 2 | 3 | ARG CCACHE_VERSION=3.7.9 4 | ARG CMAKE_VERSION=3.17.0 5 | ARG FFMPEG_VERSION=5.1.4 6 | ARG NASM_VERSION=2.15.04 7 | ARG OPENSSL_VERSION=1_1_1w 8 | ARG QT_VERSION=5.15.0 9 | ARG YASM_VERSION=1.3.0 10 | 11 | RUN yum install bzip2-devel curl-devel zlib-devel xcb-util-renderutil-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-wm-devel mesa-libGL-devel libxkbcommon-devel libxkbcommon-x11-devel libXi-devel freetype-devel -y 12 | 13 | RUN curl -O -L https://download.qt.io/official_releases/qt/5.15/${QT_VERSION}/single/qt-everywhere-src-${QT_VERSION}.tar.xz && \ 14 | tar -xf qt-everywhere-src-${QT_VERSION}.tar.xz && \ 15 | cd qt-everywhere* && \ 16 | export MAKEFLAGS=-j$(nproc) && \ 17 | ./configure -prefix /opt/Qt${QT_VERSION} -release -opensource -confirm-license -qtnamespace QtOpenCVPython -xcb -xcb-xlib -bundled-xcb-xinput -no-openssl -no-dbus -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmultimedia -skip qtpurchasing -skip qtqa -skip qtremoteobjects -skip qtrepotools -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttranslations -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip xmlpatterns -skip declarative -make libs && \ 18 | make && \ 19 | make install && \ 20 | cd .. && \ 21 | rm -rf qt-everywhere-src-${QT_VERSION} && \ 22 | rm qt-everywhere-src-${QT_VERSION}.tar.xz 23 | 24 | ENV QTDIR /opt/Qt${QT_VERSION} 25 | ENV PATH "$QTDIR/bin:$PATH" 26 | 27 | RUN mkdir ~/ffmpeg_sources && \ 28 | cd ~/ffmpeg_sources && \ 29 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 30 | tar -xf OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 31 | cd openssl-OpenSSL_${OPENSSL_VERSION} && \ 32 | # in i686, ./config detects x64 in i686 container without linux32 33 | # when run from "docker build" 34 | linux32 ./config --prefix="$HOME/ffmpeg_build" no-pinshared shared zlib && \ 35 | make -j$(getconf _NPROCESSORS_ONLN) && \ 36 | #skip installing documentation 37 | make install_sw && \ 38 | rm -rf ~/openssl_build 39 | 40 | RUN cd ~/ffmpeg_sources && \ 41 | curl -O -L http://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.bz2 && \ 42 | tar -xf nasm-${NASM_VERSION}.tar.bz2 && cd nasm-${NASM_VERSION} && ./autogen.sh && \ 43 | linux32 ./configure && \ 44 | make -j$(getconf _NPROCESSORS_ONLN) && \ 45 | make install 46 | 47 | RUN cd ~/ffmpeg_sources && \ 48 | curl -O -L http://www.tortall.net/projects/yasm/releases/yasm-${YASM_VERSION}.tar.gz && \ 49 | tar -xf yasm-${YASM_VERSION}.tar.gz && \ 50 | cd yasm-${YASM_VERSION} && \ 51 | linux32 ./configure && \ 52 | make -j$(getconf _NPROCESSORS_ONLN) && \ 53 | make install 54 | 55 | RUN cd ~/ffmpeg_sources && \ 56 | git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git && \ 57 | cd libvpx && \ 58 | linux32 ./configure --prefix="$HOME/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 59 | make -j$(getconf _NPROCESSORS_ONLN) && \ 60 | make install 61 | 62 | RUN cd ~/ffmpeg_sources && \ 63 | curl -O -L https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \ 64 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \ 65 | cd ffmpeg-${FFMPEG_VERSION} && \ 66 | PATH=~/bin:$PATH && \ 67 | PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" linux32 ./configure --prefix="$HOME/ffmpeg_build" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 68 | make -j$(getconf _NPROCESSORS_ONLN) && \ 69 | make install && \ 70 | echo "/root/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 71 | ldconfig && \ 72 | rm -rf ~/ffmpeg_sources 73 | 74 | RUN curl -O -L https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz && \ 75 | tar -xf ccache-${CCACHE_VERSION}.tar.gz && \ 76 | cd ccache-${CCACHE_VERSION} && \ 77 | linux32 ./configure && \ 78 | make -j$(getconf _NPROCESSORS_ONLN) && \ 79 | make install 80 | 81 | RUN curl -O -L https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/cmake-${CMAKE_VERSION}.tar.gz && \ 82 | tar -xf cmake-${CMAKE_VERSION}.tar.gz && \ 83 | cd cmake-${CMAKE_VERSION} && \ 84 | export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN) && \ 85 | ./configure --system-curl && \ 86 | make && \ 87 | make install && \ 88 | cd .. && \ 89 | rm -rf cmake-${CMAKE_VERSION}* 90 | 91 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/root/ffmpeg_build/lib/pkgconfig 92 | ENV LDFLAGS -L/root/ffmpeg_build/lib 93 | 94 | # in i686, yum metadata ends up with slightly wrong timestamps 95 | # which inhibits its update 96 | # https://github.com/skvark/opencv-python/issues/148 97 | RUN yum clean all 98 | 99 | ENV PATH "$HOME/bin:$PATH" 100 | -------------------------------------------------------------------------------- /docker/manylinux1/Dockerfile_i686: -------------------------------------------------------------------------------- 1 | FROM quay.io/pypa/manylinux1_i686:latest 2 | 3 | RUN curl -O -L https://download.qt.io/archive/qt/4.8/4.8.7/qt-everywhere-opensource-src-4.8.7.tar.gz && \ 4 | tar -xf qt-everywhere-opensource-src-4.8.7.tar.gz && \ 5 | cd qt-everywhere* && \ 6 | #configure does a bootstrap make under the hood 7 | #manylinux1 is too old to have `nproc` 8 | export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN) && \ 9 | #OpenCV only links against QtCore, QtGui, QtTest 10 | ./configure -prefix /opt/Qt4.8.7 -release -opensource -confirm-license -make && \ 11 | make && \ 12 | make install && \ 13 | cd .. && \ 14 | rm -rf qt-everywhere-opensource-src-4.8.7 && \ 15 | rm qt-everywhere-opensource-src-4.8.7.tar.gz 16 | 17 | ENV QTDIR /opt/Qt4.8.7 18 | ENV PATH "$QTDIR/bin:$PATH" 19 | 20 | RUN curl -O -L https://cmake.org/files/v3.9/cmake-3.9.0.tar.gz && \ 21 | tar -xf cmake-3.9.0.tar.gz && \ 22 | cd cmake-3.9.0 && \ 23 | #manylinux1 provides curl-devel equivalent and libcurl statically linked 24 | # against the same newer OpenSSL as other source-built tools 25 | # (1.0.2s as of this writing) 26 | yum -y install zlib-devel && \ 27 | #configure does a bootstrap make under the hood 28 | export MAKEFLAGS=-j$(getconf _NPROCESSORS_ONLN) && \ 29 | ./configure --system-curl && \ 30 | make && \ 31 | make install && \ 32 | cd .. && \ 33 | rm -rf cmake-3.9.0* 34 | 35 | # https://trac.ffmpeg.org/wiki/CompilationGuide/Centos#GettheDependencies 36 | # manylinux provides the toolchain and git; we provide cmake 37 | RUN yum install freetype-devel bzip2-devel zlib-devel -y && \ 38 | mkdir ~/ffmpeg_sources 39 | 40 | # Newer openssl configure requires newer perl 41 | RUN curl -O -L https://www.cpan.org/src/5.0/perl-5.20.1.tar.gz && \ 42 | tar -xf perl-5.20.1.tar.gz && \ 43 | cd perl-5.20.1 && \ 44 | ./Configure -des -Dprefix="$HOME/openssl_build" && \ 45 | #perl build scripts do much redundant work 46 | # if running "make install" separately 47 | make install -j$(getconf _NPROCESSORS_ONLN) && \ 48 | cd .. && \ 49 | rm -rf perl-5.20.1* 50 | 51 | RUN cd ~/ffmpeg_sources && \ 52 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_1_1_1c.tar.gz && \ 53 | tar -xf OpenSSL_1_1_1c.tar.gz && \ 54 | cd openssl-OpenSSL_1_1_1c && \ 55 | #in i686, ./config detects x64 in i686 container without linux32 56 | # when run from "docker build" 57 | PERL="$HOME/openssl_build/bin/perl" linux32 ./config --prefix="$HOME/ffmpeg_build" --openssldir="$HOME/ffmpeg_build" shared zlib && \ 58 | make -j$(getconf _NPROCESSORS_ONLN) && \ 59 | #skip installing documentation 60 | make install_sw && \ 61 | rm -rf ~/openssl_build 62 | 63 | RUN cd ~/ffmpeg_sources && \ 64 | curl -O -L http://www.nasm.us/pub/nasm/releasebuilds/2.14.01/nasm-2.14.01.tar.bz2 && \ 65 | tar -xf nasm-2.14.01.tar.bz2 && cd nasm-2.14.01 && ./autogen.sh && \ 66 | ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \ 67 | make -j$(getconf _NPROCESSORS_ONLN) && \ 68 | make install 69 | 70 | RUN cd ~/ffmpeg_sources && \ 71 | curl -O -L http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz && \ 72 | tar -xf yasm-1.3.0.tar.gz && \ 73 | cd yasm-1.3.0 && \ 74 | ./configure --prefix="$HOME/ffmpeg_build" --bindir="$HOME/bin" && \ 75 | make -j$(getconf _NPROCESSORS_ONLN) && \ 76 | make install 77 | 78 | RUN cd ~/ffmpeg_sources && \ 79 | git clone --depth 1 https://chromium.googlesource.com/webm/libvpx.git && \ 80 | cd libvpx && \ 81 | ./configure --prefix="$HOME/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 82 | make -j$(getconf _NPROCESSORS_ONLN) && \ 83 | make install 84 | 85 | RUN cd ~/ffmpeg_sources && \ 86 | curl -O -L https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && \ 87 | tar -xf ffmpeg-snapshot.tar.bz2 && \ 88 | cd ffmpeg && \ 89 | PATH=~/bin:$PATH && \ 90 | PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure --prefix="$HOME/ffmpeg_build" --extra-cflags="-I$HOME/ffmpeg_build/include" --extra-ldflags="-L$HOME/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 91 | make -j$(getconf _NPROCESSORS_ONLN) && \ 92 | make install && \ 93 | echo "/root/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 94 | ldconfig && \ 95 | rm -rf ~/ffmpeg_sources 96 | 97 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/root/ffmpeg_build/lib/pkgconfig 98 | ENV LDFLAGS -L/root/ffmpeg_build/lib 99 | 100 | RUN curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/uapi/linux/videodev2.h && \ 101 | curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/uapi/linux/v4l2-common.h && \ 102 | curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/uapi/linux/v4l2-controls.h && \ 103 | curl -O https://raw.githubusercontent.com/torvalds/linux/v4.14/include/linux/compiler.h && \ 104 | mv videodev2.h v4l2-common.h v4l2-controls.h compiler.h /usr/include/linux 105 | 106 | #in i686, yum metadata ends up with slightly wrong timestamps 107 | #which inhibits its update 108 | #https://github.com/skvark/opencv-python/issues/148 109 | RUN yum clean all 110 | 111 | ENV PATH "$HOME/bin:$PATH" 112 | -------------------------------------------------------------------------------- /docker/musllinux_1_2/Dockerfile_x86_64: -------------------------------------------------------------------------------- 1 | # version: 20251211 2 | # Image name: quay.io/opencv-ci/opencv-python-musllinux_1_2-x86-64 3 | FROM quay.io/pypa/musllinux_1_2_x86_64:latest 4 | 5 | ARG CCACHE_VERSION=3.7.9 6 | ARG FFMPEG_VERSION=6.1.1 7 | ARG FREETYPE_VERSION=2.13.3 8 | ARG LIBPNG_VERSION=1.6.48 9 | ARG VPX_VERSION=v1.15.1 10 | ARG NASM_VERSION=2.15.04 11 | ARG OPENSSL_VERSION=1_1_1w 12 | ARG YASM_VERSION=1.3.0 13 | ARG AOM_VERSION=v3.12.1 14 | ARG AVIF_VERSION=v1.3.0 15 | 16 | ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 17 | 18 | RUN apk add --no-cache \ 19 | build-base \ 20 | diffutils \ 21 | cmake \ 22 | bash \ 23 | git \ 24 | curl \ 25 | wget \ 26 | tar \ 27 | xz \ 28 | zlib-dev \ 29 | xz-dev \ 30 | nasm \ 31 | yasm \ 32 | pkgconfig \ 33 | openssl-dev \ 34 | libjpeg-turbo-dev \ 35 | fontconfig-dev \ 36 | freetype-dev \ 37 | expat-dev \ 38 | libpng-dev \ 39 | alsa-lib-dev \ 40 | musl-dev \ 41 | ttf-dejavu \ 42 | linux-headers \ 43 | perl 44 | 45 | RUN apk del libpng-dev 46 | 47 | ### libpng 48 | RUN mkdir ~/libpng_sources && \ 49 | cd ~/libpng_sources && \ 50 | curl -O -L https://download.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz && \ 51 | tar -xf libpng-${LIBPNG_VERSION}.tar.gz && \ 52 | cd libpng-${LIBPNG_VERSION} && \ 53 | ./configure --prefix=/usr/local && \ 54 | make && \ 55 | make install && \ 56 | cd .. && \ 57 | rm -rf ~/libpng_sources 58 | 59 | ### freetype 60 | RUN mkdir ~/freetype_sources && \ 61 | cd ~/freetype_sources && \ 62 | curl -O -L https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \ 63 | tar -xf freetype-${FREETYPE_VERSION}.tar.gz && \ 64 | cd freetype-${FREETYPE_VERSION} && \ 65 | ./configure --prefix="/ffmpeg_build" --enable-freetype-config && \ 66 | make && \ 67 | make install && \ 68 | cd .. && \ 69 | rm -rf ~/freetype_sources 70 | 71 | ### OpenSSL 72 | RUN mkdir ~/openssl_sources && \ 73 | cd ~/openssl_sources && \ 74 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 75 | tar -xf OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 76 | cd openssl-OpenSSL_${OPENSSL_VERSION} && \ 77 | ./config --prefix="/ffmpeg_build" --openssldir="/ffmpeg_build" no-pinshared shared zlib && \ 78 | make -j$(getconf _NPROCESSORS_ONLN) && \ 79 | make install_sw && \ 80 | cd .. && \ 81 | rm -rf ~/openssl_build ~/openssl_sources 82 | 83 | ### libvpx 84 | RUN mkdir ~/libvpx_sources && \ 85 | cd ~/libvpx_sources && \ 86 | git clone --depth 1 -b ${VPX_VERSION} https://chromium.googlesource.com/webm/libvpx.git && \ 87 | cd libvpx && \ 88 | ./configure --prefix="/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 89 | make -j$(getconf _NPROCESSORS_ONLN) && \ 90 | make install && \ 91 | cd .. && \ 92 | rm -rf ~/libvpx_sources 93 | 94 | 95 | ### aom 96 | RUN mkdir -p /tmp/aom_sources && \ 97 | cd /tmp/aom_sources && \ 98 | git clone --depth 1 -b ${AOM_VERSION} https://aomedia.googlesource.com/aom && \ 99 | mkdir build && cd build && \ 100 | cmake \ 101 | -DCMAKE_C_COMPILER=$(dirname $(which g++))/gcc \ 102 | -DCMAKE_INSTALL_PREFIX=/usr \ 103 | -DBUILD_SHARED_LIBS=ON \ 104 | -DENABLE_TESTS=OFF \ 105 | -DENABLE_EXAMPLES=OFF \ 106 | ../aom && \ 107 | make -j$(getconf _NPROCESSORS_ONLN) && \ 108 | make install 109 | ### avif 110 | RUN mkdir ~/avif_sources && \ 111 | cd ~/avif_sources && \ 112 | git clone -b ${AVIF_VERSION} https://github.com/AOMediaCodec/libavif.git && \ 113 | mkdir build && cd build && \ 114 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DAVIF_CODEC_AOM=SYSTEM -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_APPS=OFF ../libavif && \ 115 | make -j$(getconf _NPROCESSORS_ONLN) && \ 116 | make install && \ 117 | cd .. && \ 118 | rm -rf ~/avif_sources 119 | 120 | ### ffmpeg 121 | RUN mkdir -p /ffmpeg_sources && \ 122 | cd /ffmpeg_sources && \ 123 | curl -LO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 124 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 125 | cd ffmpeg-${FFMPEG_VERSION} && \ 126 | PKG_CONFIG_PATH="/ffmpeg_build/lib/pkgconfig" ./configure \ 127 | --prefix="/ffmpeg_build" \ 128 | --extra-cflags="-I/ffmpeg_build/include" \ 129 | --extra-ldflags="-L/ffmpeg_build/lib" \ 130 | --enable-openssl \ 131 | --enable-libvpx \ 132 | --enable-shared \ 133 | --enable-pic \ 134 | --disable-indev=v4l2 \ 135 | --disable-outdev=v4l2 && \ 136 | make -j$(getconf _NPROCESSORS_ONLN) && \ 137 | make install && \ 138 | rm -rf /ffmpeg_sources 139 | 140 | ### ccache 141 | RUN curl -O -L https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz && \ 142 | tar -xf ccache-${CCACHE_VERSION}.tar.gz && \ 143 | cd ccache-${CCACHE_VERSION} && \ 144 | ./configure && \ 145 | make -j$(getconf _NPROCESSORS_ONLN) && \ 146 | make install && \ 147 | cd .. && \ 148 | rm -rf ccache-${CCACHE_VERSION}.tar.gz 149 | 150 | # user`s UID is 1001 151 | RUN adduser -D -u 1001 ci && mkdir /io && chown ci:ci /io && \ 152 | chown -R ci:ci /ffmpeg_build 153 | 154 | USER ci 155 | 156 | RUN git config --global --add safe.directory /io 157 | ENV PATH="/ffmpeg_build/bin:$PATH" 158 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/ffmpeg_build/lib/pkgconfig 159 | ENV LDFLAGS -L/ffmpeg_build/lib 160 | ENV PATH "$HOME/bin:$PATH" 161 | ENV LD_LIBRARY_PATH="/ffmpeg_build/lib:$LD_LIBRARY_PATH" 162 | -------------------------------------------------------------------------------- /docker/manylinux_2_28/Dockerfile_aarch64: -------------------------------------------------------------------------------- 1 | # Version: 20251013 2 | # Image name: quay.io/opencv-ci/opencv-python-manylinux_2_28-aarch64 3 | 4 | FROM quay.io/pypa/manylinux_2_28_aarch64:latest 5 | 6 | ARG FFMPEG_VERSION=5.1.6 7 | ARG FREETYPE_VERSION=2.13.3 8 | ARG LIBPNG_VERSION=1.6.48 9 | ARG VPX_VERSION=v1.15.1 10 | ARG QT_VERSION=5.15.16 11 | ARG AOM_VERSION=v3.12.1 12 | ARG AVIF_VERSION=v1.3.0 13 | 14 | ENV LD_LIBRARY_PATH /usr/local/lib:$LD_LIBRARY_PATH 15 | 16 | # epel-release need for aarch64 to get openblas packages 17 | RUN yum install zlib-devel curl-devel xcb-util-renderutil-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-wm-devel mesa-libGL-devel libxkbcommon-devel libxkbcommon-x11-devel libXi-devel lapack-devel epel-release -y && \ 18 | yum install openblas-devel dejavu-sans-fonts ccache yasm nasm ninja-build openssl openssl-devel -y && \ 19 | # libpng will be built from source 20 | yum remove libpng -y 21 | 22 | RUN mkdir ~/libpng_sources && \ 23 | cd ~/libpng_sources && \ 24 | curl -O -L https://download.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz && \ 25 | tar -xf libpng-${LIBPNG_VERSION}.tar.gz && \ 26 | cd libpng-${LIBPNG_VERSION} && \ 27 | ./configure --prefix=/usr/local && \ 28 | make && \ 29 | make install && \ 30 | cd .. && \ 31 | rm -rf ~/libpng_sources 32 | 33 | RUN mkdir ~/freetype_sources && \ 34 | cd ~/freetype_sources && \ 35 | curl -O -L https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \ 36 | tar -xf freetype-${FREETYPE_VERSION}.tar.gz && \ 37 | cd freetype-${FREETYPE_VERSION} && \ 38 | ./configure --prefix="/ffmpeg_build" --enable-freetype-config && \ 39 | make && \ 40 | make install && \ 41 | cd .. && \ 42 | rm -rf ~/freetype_sources 43 | 44 | RUN curl -O -L https://download.qt.io/archive/qt/5.15/${QT_VERSION}/single/qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 45 | tar -xf qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 46 | cd qt-everywhere-src-${QT_VERSION} && \ 47 | export MAKEFLAGS=-j$(nproc) && \ 48 | ./configure -prefix /opt/Qt${QT_VERSION} -release -opensource -confirm-license -qtnamespace QtOpenCVPython -xcb -xcb-xlib -bundled-xcb-xinput -no-openssl -no-dbus -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmultimedia -skip qtpurchasing -skip qtqa -skip qtremoteobjects -skip qtrepotools -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttranslations -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip xmlpatterns -skip declarative -make libs && \ 49 | make && \ 50 | make install && \ 51 | cd .. && \ 52 | rm -rf qt-everywhere* 53 | 54 | ENV QTDIR /opt/Qt${QT_VERSION} 55 | ENV PATH "$QTDIR/bin:$PATH" 56 | 57 | RUN mkdir ~/libvpx_sources && \ 58 | cd ~/libvpx_sources && \ 59 | git clone --depth 1 -b ${VPX_VERSION} https://chromium.googlesource.com/webm/libvpx.git && \ 60 | cd libvpx && \ 61 | ./configure --prefix="/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 62 | make -j$(getconf _NPROCESSORS_ONLN) && \ 63 | make install && \ 64 | cd .. && \ 65 | rm -rf ~/libvpx_sources 66 | 67 | RUN mkdir ~/aom_sources && \ 68 | cd ~/aom_sources && \ 69 | git clone --depth 1 -b ${AOM_VERSION} https://aomedia.googlesource.com/aom && \ 70 | mkdir build && cd build && \ 71 | cmake -DCMAKE_C_COMPILER=$(dirname $(which g++))/gcc -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=ON -DENABLE_TESTS=OFF ../aom/ && \ 72 | make -j$(getconf _NPROCESSORS_ONLN) && \ 73 | make install && \ 74 | cd / && rm -rf ~/aom_sources 75 | 76 | RUN mkdir ~/avif_sources && \ 77 | cd ~/avif_sources && \ 78 | git clone -b ${AVIF_VERSION} https://github.com/AOMediaCodec/libavif.git && \ 79 | mkdir build && cd build && \ 80 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DAVIF_CODEC_AOM=SYSTEM -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_APPS=OFF ../libavif && \ 81 | make -j$(getconf _NPROCESSORS_ONLN) && \ 82 | make install && \ 83 | cd / && rm -rf ~/avif_sources 84 | 85 | RUN mkdir ~/ffmpeg_sources && \ 86 | cd ~/ffmpeg_sources && \ 87 | curl -O -L https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 88 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 89 | cd ffmpeg-${FFMPEG_VERSION} && \ 90 | PATH=~/bin:$PATH && \ 91 | PKG_CONFIG_PATH="/ffmpeg_build/lib/pkgconfig" ./configure --prefix="/ffmpeg_build" --extra-cflags="-I/ffmpeg_build/include" --extra-ldflags="-L/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 92 | make -j$(getconf _NPROCESSORS_ONLN) && \ 93 | make install && \ 94 | echo "/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 95 | ldconfig && \ 96 | rm -rf ~/ffmpeg_sources 97 | 98 | # Self-hosted runner UID is 1004 99 | RUN useradd ci -m -s /bin/bash -G users --uid=1004 && \ 100 | mkdir /io && \ 101 | chown -R ci:ci /io && \ 102 | # This needs to find ffmpeg packages from ci user 103 | chown -R ci:ci /ffmpeg_build && \ 104 | # This calls in mutlibuild scripts and cannot be run without permissions 105 | chown -R ci:ci /opt/_internal/pipx/venvs/auditwheel 106 | 107 | USER ci 108 | 109 | # Git security vulnerability: https://github.blog/2022-04-12-git-security-vulnerability-announced 110 | RUN git config --global --add safe.directory /io 111 | 112 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/ffmpeg_build/lib/pkgconfig 113 | ENV LDFLAGS -L/ffmpeg_build/lib 114 | ENV PATH "$HOME/bin:$PATH" 115 | -------------------------------------------------------------------------------- /docker/manylinux_2_28/Dockerfile_x86_64: -------------------------------------------------------------------------------- 1 | # Version: 20251013 2 | # Image name: quay.io/opencv-ci/opencv-python-manylinux_2_28-x86-64 3 | 4 | FROM quay.io/pypa/manylinux_2_28_x86_64:latest 5 | 6 | ARG FFMPEG_VERSION=5.1.6 7 | ARG FREETYPE_VERSION=2.13.3 8 | ARG LIBPNG_VERSION=1.6.48 9 | ARG VPX_VERSION=v1.15.1 10 | ARG QT_VERSION=5.15.16 11 | ARG AOM_VERSION=v3.12.1 12 | ARG AVIF_VERSION=v1.3.0 13 | 14 | ENV LD_LIBRARY_PATH /usr/local/lib:$LD_LIBRARY_PATH 15 | 16 | # epel-release need for aarch64 to get openblas packages 17 | RUN yum install zlib-devel curl-devel xcb-util-renderutil-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-wm-devel mesa-libGL-devel libxkbcommon-devel libxkbcommon-x11-devel libXi-devel lapack-devel epel-release -y && \ 18 | yum install openblas-devel dejavu-sans-fonts ccache yasm nasm ninja-build openssl openssl-devel -y && \ 19 | # libpng will be built from source 20 | yum remove libpng -y 21 | 22 | RUN mkdir ~/libpng_sources && \ 23 | cd ~/libpng_sources && \ 24 | curl -O -L https://download.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz && \ 25 | tar -xf libpng-${LIBPNG_VERSION}.tar.gz && \ 26 | cd libpng-${LIBPNG_VERSION} && \ 27 | ./configure --prefix=/usr/local && \ 28 | make && \ 29 | make install && \ 30 | cd .. && \ 31 | rm -rf ~/libpng_sources 32 | 33 | RUN mkdir ~/freetype_sources && \ 34 | cd ~/freetype_sources && \ 35 | curl -O -L https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \ 36 | tar -xf freetype-${FREETYPE_VERSION}.tar.gz && \ 37 | cd freetype-${FREETYPE_VERSION} && \ 38 | ./configure --prefix="/ffmpeg_build" --enable-freetype-config && \ 39 | make && \ 40 | make install && \ 41 | cd .. && \ 42 | rm -rf ~/freetype_sources 43 | 44 | RUN curl -O -L https://download.qt.io/archive/qt/5.15/${QT_VERSION}/single/qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 45 | tar -xf qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 46 | cd qt-everywhere-src-${QT_VERSION} && \ 47 | export MAKEFLAGS=-j$(nproc) && \ 48 | ./configure -prefix /opt/Qt${QT_VERSION} -release -opensource -confirm-license -qtnamespace QtOpenCVPython -xcb -xcb-xlib -bundled-xcb-xinput -no-openssl -no-dbus -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmultimedia -skip qtpurchasing -skip qtqa -skip qtremoteobjects -skip qtrepotools -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttranslations -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip xmlpatterns -skip declarative -make libs && \ 49 | make && \ 50 | make install && \ 51 | cd .. && \ 52 | rm -rf qt-everywhere* 53 | 54 | ENV QTDIR /opt/Qt${QT_VERSION} 55 | ENV PATH "$QTDIR/bin:$PATH" 56 | 57 | RUN mkdir ~/libvpx_sources && \ 58 | cd ~/libvpx_sources && \ 59 | git clone --depth 1 -b ${VPX_VERSION} https://chromium.googlesource.com/webm/libvpx.git && \ 60 | cd libvpx && \ 61 | ./configure --prefix="/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 62 | make -j$(getconf _NPROCESSORS_ONLN) && \ 63 | make install && \ 64 | cd .. && \ 65 | rm -rf ~/libvpx_sources 66 | 67 | RUN mkdir ~/aom_sources && \ 68 | cd ~/aom_sources && \ 69 | git clone --depth 1 -b ${AOM_VERSION} https://aomedia.googlesource.com/aom && \ 70 | mkdir build && cd build && \ 71 | cmake -DCMAKE_C_COMPILER=$(dirname $(which g++))/gcc -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=ON -DENABLE_TESTS=OFF ../aom/ && \ 72 | make -j$(getconf _NPROCESSORS_ONLN) && \ 73 | make install && \ 74 | cd / && rm -rf ~/aom_sources 75 | 76 | RUN mkdir ~/avif_sources && \ 77 | cd ~/avif_sources && \ 78 | git clone -b ${AVIF_VERSION} https://github.com/AOMediaCodec/libavif.git && \ 79 | mkdir build && cd build && \ 80 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DAVIF_CODEC_AOM=SYSTEM -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_APPS=OFF ../libavif && \ 81 | make -j$(getconf _NPROCESSORS_ONLN) && \ 82 | make install && \ 83 | cd / && rm -rf ~/avif_sources 84 | 85 | RUN mkdir ~/ffmpeg_sources && \ 86 | cd ~/ffmpeg_sources && \ 87 | curl -O -L https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 88 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 89 | cd ffmpeg-${FFMPEG_VERSION} && \ 90 | PATH=~/bin:$PATH && \ 91 | PKG_CONFIG_PATH="/ffmpeg_build/lib/pkgconfig" ./configure --prefix="/ffmpeg_build" --extra-cflags="-I/ffmpeg_build/include" --extra-ldflags="-L/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 92 | make -j$(getconf _NPROCESSORS_ONLN) && \ 93 | make install && \ 94 | echo "/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 95 | ldconfig && \ 96 | rm -rf ~/ffmpeg_sources 97 | 98 | # GitHub Actions user`s UID is 1001 99 | RUN useradd ci -m -s /bin/bash -G users --uid=1001 && \ 100 | mkdir /io && \ 101 | chown -R ci:ci /io && \ 102 | # This needs to find ffmpeg packages from ci user 103 | chown -R ci:ci /ffmpeg_build && \ 104 | # This calls in mutlibuild scripts and cannot be run without permissions 105 | chown -R ci:ci /opt/_internal/pipx/venvs/auditwheel 106 | 107 | USER ci 108 | 109 | # Git security vulnerability: https://github.blog/2022-04-12-git-security-vulnerability-announced 110 | RUN git config --global --add safe.directory /io 111 | 112 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/ffmpeg_build/lib/pkgconfig 113 | ENV LDFLAGS -L/ffmpeg_build/lib 114 | ENV PATH "$HOME/bin:$PATH" 115 | -------------------------------------------------------------------------------- /docker/musllinux_1_2/Dockerfile_aarch64: -------------------------------------------------------------------------------- 1 | # version: 20251211 2 | # Image name: quay.io/opencv-ci/opencv-python-musllinux_1_2-aarch64 3 | FROM quay.io/pypa/musllinux_1_2_aarch64:latest 4 | 5 | ARG CCACHE_VERSION=3.7.9 6 | ARG FFMPEG_VERSION=6.1.1 7 | ARG FREETYPE_VERSION=2.13.3 8 | ARG LIBPNG_VERSION=1.6.48 9 | ARG VPX_VERSION=v1.15.1 10 | ARG NASM_VERSION=2.15.04 11 | ARG OPENSSL_VERSION=1_1_1w 12 | ARG YASM_VERSION=1.3.0 13 | ARG AOM_VERSION=v3.12.1 14 | ARG AVIF_VERSION=v1.3.0 15 | 16 | ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH 17 | 18 | RUN apk add --no-cache \ 19 | build-base \ 20 | diffutils \ 21 | cmake \ 22 | bash \ 23 | git \ 24 | curl \ 25 | wget \ 26 | tar \ 27 | xz \ 28 | zlib-dev \ 29 | xz-dev \ 30 | nasm \ 31 | yasm \ 32 | pkgconfig \ 33 | openssl-dev \ 34 | libjpeg-turbo-dev \ 35 | fontconfig-dev \ 36 | freetype-dev \ 37 | expat-dev \ 38 | libpng-dev \ 39 | alsa-lib-dev \ 40 | musl-dev \ 41 | ttf-dejavu \ 42 | linux-headers \ 43 | perl 44 | 45 | RUN apk del libpng-dev 46 | 47 | ### libpng 48 | RUN mkdir ~/libpng_sources && \ 49 | cd ~/libpng_sources && \ 50 | curl -O -L https://download.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz && \ 51 | tar -xf libpng-${LIBPNG_VERSION}.tar.gz && \ 52 | cd libpng-${LIBPNG_VERSION} && \ 53 | ./configure --prefix=/usr/local && \ 54 | make && \ 55 | make install && \ 56 | cd .. && \ 57 | rm -rf ~/libpng_sources 58 | 59 | ### freetype 60 | RUN mkdir ~/freetype_sources && \ 61 | cd ~/freetype_sources && \ 62 | curl -O -L https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \ 63 | tar -xf freetype-${FREETYPE_VERSION}.tar.gz && \ 64 | cd freetype-${FREETYPE_VERSION} && \ 65 | ./configure --prefix="/ffmpeg_build" --enable-freetype-config && \ 66 | make && \ 67 | make install && \ 68 | cd .. && \ 69 | rm -rf ~/freetype_sources 70 | 71 | ### OpenSSL 72 | RUN mkdir ~/openssl_sources && \ 73 | cd ~/openssl_sources && \ 74 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 75 | tar -xf OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 76 | cd openssl-OpenSSL_${OPENSSL_VERSION} && \ 77 | ./config --prefix="/ffmpeg_build" --openssldir="/ffmpeg_build" no-pinshared shared zlib && \ 78 | make -j$(getconf _NPROCESSORS_ONLN) && \ 79 | make install_sw && \ 80 | cd .. && \ 81 | rm -rf ~/openssl_build ~/openssl_sources 82 | 83 | ### libvpx 84 | RUN mkdir ~/libvpx_sources && \ 85 | cd ~/libvpx_sources && \ 86 | git clone --depth 1 -b ${VPX_VERSION} https://chromium.googlesource.com/webm/libvpx.git && \ 87 | cd libvpx && \ 88 | ./configure --prefix="/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 89 | make -j$(getconf _NPROCESSORS_ONLN) && \ 90 | make install && \ 91 | cd .. && \ 92 | rm -rf ~/libvpx_sources 93 | 94 | 95 | ### aom 96 | RUN mkdir -p /tmp/aom_sources && \ 97 | cd /tmp/aom_sources && \ 98 | git clone --depth 1 -b ${AOM_VERSION} https://aomedia.googlesource.com/aom && \ 99 | mkdir build && cd build && \ 100 | cmake \ 101 | -DCMAKE_C_COMPILER=$(dirname $(which g++))/gcc \ 102 | -DCMAKE_INSTALL_PREFIX=/usr \ 103 | -DBUILD_SHARED_LIBS=ON \ 104 | -DENABLE_TESTS=OFF \ 105 | -DENABLE_EXAMPLES=OFF \ 106 | ../aom && \ 107 | make -j$(getconf _NPROCESSORS_ONLN) && \ 108 | make install 109 | ### avif 110 | RUN mkdir ~/avif_sources && \ 111 | cd ~/avif_sources && \ 112 | git clone -b ${AVIF_VERSION} https://github.com/AOMediaCodec/libavif.git && \ 113 | mkdir build && cd build && \ 114 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DAVIF_CODEC_AOM=SYSTEM -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_APPS=OFF ../libavif && \ 115 | make -j$(getconf _NPROCESSORS_ONLN) && \ 116 | make install && \ 117 | cd .. && \ 118 | rm -rf ~/avif_sources 119 | 120 | ### ffmpeg 121 | RUN mkdir -p /ffmpeg_sources && \ 122 | cd /ffmpeg_sources && \ 123 | curl -LO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 124 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 125 | cd ffmpeg-${FFMPEG_VERSION} && \ 126 | PKG_CONFIG_PATH="/ffmpeg_build/lib/pkgconfig" ./configure \ 127 | --prefix="/ffmpeg_build" \ 128 | --extra-cflags="-I/ffmpeg_build/include" \ 129 | --extra-ldflags="-L/ffmpeg_build/lib" \ 130 | --enable-openssl \ 131 | --enable-libvpx \ 132 | --enable-shared \ 133 | --enable-pic \ 134 | --disable-indev=v4l2 \ 135 | --disable-outdev=v4l2 && \ 136 | make -j$(getconf _NPROCESSORS_ONLN) && \ 137 | make install && \ 138 | rm -rf /ffmpeg_sources 139 | 140 | ### ccache 141 | RUN curl -O -L https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz && \ 142 | tar -xf ccache-${CCACHE_VERSION}.tar.gz && \ 143 | cd ccache-${CCACHE_VERSION} && \ 144 | ./configure && \ 145 | make -j$(getconf _NPROCESSORS_ONLN) && \ 146 | make install && \ 147 | cd .. && \ 148 | rm -rf ccache-${CCACHE_VERSION}.tar.gz 149 | 150 | # Self-hosted runner UID is 1004 151 | RUN useradd ci -m -s /bin/bash -G users --uid=1004 && \ 152 | mkdir /io && \ 153 | chown -R ci:ci /io && \ 154 | # This needs to find ffmpeg packages from ci user 155 | chown -R ci:ci /ffmpeg_build && \ 156 | # This calls in mutlibuild scripts and cannot be run without permissions 157 | chown -R ci:ci /opt/_internal/pipx/venvs/auditwheel 158 | 159 | USER ci 160 | 161 | RUN git config --global --add safe.directory /io 162 | ENV PATH="/ffmpeg_build/bin:$PATH" 163 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/ffmpeg_build/lib/pkgconfig 164 | ENV LDFLAGS -L/ffmpeg_build/lib 165 | ENV PATH "$HOME/bin:$PATH" 166 | ENV LD_LIBRARY_PATH="/ffmpeg_build/lib:$LD_LIBRARY_PATH" 167 | -------------------------------------------------------------------------------- /travis_config.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #Customize multibuild logic that is run after entering docker. 3 | #Sourced by docker_build_wrap.sh and docker_test_wrap.sh . 4 | #Runs in Docker, so only the vars passed to `docker run' exist. 5 | #See multibuild/README.rst 6 | echo "=== Loading config.sh === " 7 | 8 | # To see build progress 9 | function build_wheel { 10 | build_bdist_wheel $@ 11 | } 12 | 13 | function bdist_wheel_cmd { 14 | # copied from multibuild's common_utils.sh 15 | # add osx deployment target so it doesn't default to 10.6 16 | local abs_wheelhouse=$1 17 | # install all required packages in pyproject.toml, because bdist_wheel does not do it 18 | python${PYTHON_VERSION} -m pip install toml && python${PYTHON_VERSION} -c 'import toml; c = toml.load("pyproject.toml"); print("\n".join(c["build-system"]["requires"]))' | python${PYTHON_VERSION} -m pip install -r /dev/stdin 19 | CI_BUILD=1 python${PYTHON_VERSION} setup.py bdist_wheel --py-limited-api=cp37 -v 20 | cp dist/*.whl $abs_wheelhouse 21 | if [ -z "$IS_OSX" ]; then 22 | # this path can be changed in the latest manylinux image 23 | TOOLS_PATH=/opt/_internal/pipx/venvs/auditwheel 24 | /opt/python/cp39-cp39/bin/python -m venv $TOOLS_PATH 25 | source $TOOLS_PATH/bin/activate 26 | python patch_auditwheel_whitelist.py 27 | deactivate 28 | fi 29 | if [ -n "$USE_CCACHE" -a -z "$BREW_BOOTSTRAP_MODE" ]; then ccache -s; fi 30 | } 31 | 32 | if [ -n "$IS_OSX" ]; then 33 | echo " > OSX environment " 34 | export MAKEFLAGS="-j$(sysctl -n hw.ncpu)" 35 | else 36 | echo " > Linux environment " 37 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/Qt5.15.16/lib 38 | export MAKEFLAGS="-j$(grep -E '^processor[[:space:]]*:' /proc/cpuinfo | wc -l)" 39 | CURRENT_ARCH=$(uname -m) 40 | if [[ $CURRENT_ARCH == 'aarch64' ]]; then 41 | # To avoid network issues with pypi.org on OpenCV CN machines 42 | #export PIP_INDEX_URL=https://pypi.org/simple 43 | echo "Running for linux aarch64" 44 | fi 45 | fi 46 | 47 | if [ -n "$IS_OSX" ]; then 48 | 49 | source travis_osx_brew_cache.sh 50 | 51 | BREW_SLOW_BUILIDING_PACKAGES=$(printf '%s\n' \ 52 | "cmake 15" \ 53 | "ffmpeg 10" \ 54 | ) 55 | 56 | function generate_ffmpeg_formula { 57 | local FF="ffmpeg" 58 | local LFF="ffmpeg" 59 | local FF_FORMULA; FF_FORMULA=$(brew formula "${FF}") 60 | local LFF_FORMULA; LFF_FORMULA="$(dirname "$FF_FORMULA")/${LFF}.rb" 61 | 62 | local REGENERATE 63 | if [ -f "$LFF_FORMULA" ]; then 64 | local UPSTREAM_VERSION VERSION 65 | _brew_parse_package_info "$FF" " " UPSTREAM_VERSION _ _ 66 | _brew_parse_package_info "$LFF" " " VERSION _ _ || REGENERATE=1 67 | #`rebuild` clause is ignored on `brew bottle` and deleted 68 | # from newly-generated formula on `brew bottle --merge` for some reason 69 | # so can't compare rebuild numbers 70 | if [ "$UPSTREAM_VERSION" != "$VERSION" ]; then 71 | REGENERATE=1 72 | fi 73 | else 74 | REGENERATE=1 75 | fi 76 | if [ -n "$REGENERATE" ]; then 77 | echo "Regenerating custom ffmpeg formula" 78 | # Bottle block syntax: https://docs.brew.sh/Bottles#bottle-dsl-domain-specific-language 79 | perl -wpe 'BEGIN {our ($found_blank, $bottle_block);} 80 | if (/(^class )(Ffmpeg)(\s.*)/) {$_=$1."Opencv".$3."\n"; next;} 81 | if (!$found_blank && /^$/) {$_.="conflicts_with \"ffmpeg\"\n\n"; $found_blank=1; next;} 82 | if (!$bottle_block && /^\s*bottle do$/) { $bottle_block=1; next; } 83 | if ($bottle_block) { if (/^\s*end\s*$/) { $bottle_block=0} elsif (/^\s*sha256\s/) {$_=""} next; } 84 | if (/^\s*depends_on "(x264|x265|xvid|frei0r|rubberband|libvidstab)"$/) {$_=""; next;} 85 | if (/^\s*--enable-(gpl|libx264|libx265|libxvid|frei0r|librubberband|libvidstab)$/) {$_=""; next;} 86 | ' <"$FF_FORMULA" >"$LFF_FORMULA" 87 | diff -u "$FF_FORMULA" "$LFF_FORMULA" || test $? -le 1 88 | 89 | ( cd "$(dirname "$LFF_FORMULA")" 90 | # This is the official way to add a formula 91 | # https://docs.brew.sh/Formula-Cookbook#commit 92 | git add "$(basename "$LFF_FORMULA")" 93 | git commit -m "add/update custom ffmpeg ${VERSION}" 94 | ) 95 | fi 96 | } 97 | 98 | fi 99 | 100 | function pre_build { 101 | echo "Starting pre-build" 102 | set -e -o pipefail 103 | 104 | if [ -n "$IS_OSX" ]; then 105 | brew install lapack 106 | brew install libavif 107 | fi 108 | 109 | if [ -n "$IS_OSX" ]; then 110 | echo "Running for OSX" 111 | 112 | local CACHE_STAGE;# (echo "$TRAVIS_BUILD_STAGE_NAME" | grep -qiF "final") || CACHE_STAGE=1 113 | CACHE_STAGE= 114 | export HOMEBREW_NO_AUTO_UPDATE=1 115 | 116 | echo 'Installing FFmpeg' 117 | 118 | brew update 119 | generate_ffmpeg_formula 120 | brew_add_local_bottles 121 | brew install --build-bottle ffmpeg 122 | # It needs when we use not the latest ffmpeg formula 123 | brew link ffmpeg 124 | 125 | if [ -n "$CACHE_STAGE" ]; then 126 | brew_go_bootstrap_mode 0 127 | return 0 128 | fi 129 | 130 | # Have to install macpython late to avoid conflict with Homebrew Python update 131 | before_install 132 | 133 | else 134 | echo "Running for linux" 135 | fi 136 | } 137 | 138 | function run_tests { 139 | # Runs tests on installed distribution from an empty directory 140 | echo "Run tests..." 141 | echo $PWD 142 | 143 | PYTHON=python$PYTHON_VERSION 144 | 145 | echo "Running for linux" 146 | 147 | if [ $PYTHON == "python3.7" ]; then 148 | $PYTHON -m pip install -U numpy==1.19.4 149 | fi 150 | cd /io/tests 151 | $PYTHON get_build_info.py 152 | 153 | cd /io/opencv 154 | export OPENCV_TEST_DATA_PATH=/io/opencv_extra/testdata 155 | 156 | test_wheels 157 | pylint_test 158 | } 159 | 160 | function test_wheels { 161 | 162 | echo "Starting OpenCV tests..." 163 | 164 | #Test package 165 | $PYTHON modules/python/test/test.py -v --repo . 166 | } 167 | 168 | function pylint_test { 169 | 170 | echo "Starting Pylint tests..." 171 | 172 | $PYTHON -m pip install pylint==2.15.9 173 | cd /io/tests 174 | $PYTHON -m pylint /io/opencv/samples/python/squares.py 175 | } 176 | 177 | export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' 178 | set -x 179 | -------------------------------------------------------------------------------- /docker/manylinux2014/Dockerfile_x86_64: -------------------------------------------------------------------------------- 1 | # Version: 20250630 2 | # Image name: quay.io/opencv-ci/opencv-python-manylinux2014-x86-64 3 | 4 | FROM quay.io/pypa/manylinux2014_x86_64:latest 5 | 6 | ARG CCACHE_VERSION=3.7.9 7 | ARG FFMPEG_VERSION=5.1.6 8 | ARG FREETYPE_VERSION=2.13.3 9 | ARG LIBPNG_VERSION=1.6.48 10 | ARG VPX_VERSION=v1.15.1 11 | ARG NASM_VERSION=2.15.04 12 | ARG OPENSSL_VERSION=1_1_1w 13 | ARG QT_VERSION=5.15.16 14 | ARG YASM_VERSION=1.3.0 15 | ARG AOM_VERSION=v3.12.1 16 | ARG AVIF_VERSION=v1.3.0 17 | 18 | ENV LD_LIBRARY_PATH /usr/local/lib:$LD_LIBRARY_PATH 19 | 20 | # epel-release need for aarch64 to get openblas packages 21 | RUN yum install zlib-devel curl-devel xcb-util-renderutil-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-wm-devel mesa-libGL-devel libxkbcommon-devel libxkbcommon-x11-devel libXi-devel lapack-devel epel-release -y && \ 22 | yum install openblas-devel dejavu-sans-fonts -y && \ 23 | cp /usr/include/openblas/*.h /usr/include/ && \ 24 | cp /usr/include/lapacke/lapacke*.h /usr/include/ && \ 25 | # libpng will be built from source 26 | yum remove libpng -y 27 | 28 | RUN mkdir ~/libpng_sources && \ 29 | cd ~/libpng_sources && \ 30 | curl -O -L https://download.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz && \ 31 | tar -xf libpng-${LIBPNG_VERSION}.tar.gz && \ 32 | cd libpng-${LIBPNG_VERSION} && \ 33 | ./configure --prefix=/usr/local && \ 34 | make && \ 35 | make install && \ 36 | cd .. && \ 37 | rm -rf ~/libpng_sources 38 | 39 | RUN mkdir ~/freetype_sources && \ 40 | cd ~/freetype_sources && \ 41 | curl -O -L https://download.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \ 42 | tar -xf freetype-${FREETYPE_VERSION}.tar.gz && \ 43 | cd freetype-${FREETYPE_VERSION} && \ 44 | ./configure --prefix="/ffmpeg_build" --enable-freetype-config && \ 45 | make && \ 46 | make install && \ 47 | cd .. && \ 48 | rm -rf ~/freetype_sources 49 | 50 | RUN curl -O -L https://download.qt.io/archive/qt/5.15/${QT_VERSION}/single/qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 51 | tar -xf qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 52 | cd qt-everywhere-src-${QT_VERSION} && \ 53 | export MAKEFLAGS=-j$(nproc) && \ 54 | ./configure -prefix /opt/Qt${QT_VERSION} -release -opensource -confirm-license -qtnamespace QtOpenCVPython -xcb -xcb-xlib -bundled-xcb-xinput -no-openssl -no-dbus -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmultimedia -skip qtpurchasing -skip qtqa -skip qtremoteobjects -skip qtrepotools -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttranslations -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip xmlpatterns -skip declarative -make libs && \ 55 | make && \ 56 | make install && \ 57 | cd .. && \ 58 | rm -rf qt-everywhere* 59 | 60 | ENV QTDIR /opt/Qt${QT_VERSION} 61 | ENV PATH "$QTDIR/bin:$PATH" 62 | 63 | RUN mkdir ~/openssl_sources && \ 64 | cd ~/openssl_sources && \ 65 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 66 | tar -xf OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 67 | cd openssl-OpenSSL_${OPENSSL_VERSION} && \ 68 | ./config --prefix="/ffmpeg_build" --openssldir="/ffmpeg_build" no-pinshared shared zlib && \ 69 | make -j$(getconf _NPROCESSORS_ONLN) && \ 70 | # skip installing documentation 71 | make install_sw && \ 72 | cd .. && \ 73 | rm -rf ~/openssl_build ~/openssl_sources 74 | 75 | RUN mkdir ~/nasm_sources && \ 76 | cd ~/nasm_sources && \ 77 | curl -O -L http://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.gz && \ 78 | tar -xf nasm-${NASM_VERSION}.tar.gz && cd nasm-${NASM_VERSION} && ./autogen.sh && \ 79 | ./configure --prefix="/ffmpeg_build" --bindir="$HOME/bin" && \ 80 | make -j$(getconf _NPROCESSORS_ONLN) && \ 81 | make install && \ 82 | cd .. && \ 83 | rm -rf ~/nasm_sources 84 | 85 | RUN mkdir ~/yasm_sources && \ 86 | cd ~/yasm_sources && \ 87 | curl -O -L http://www.tortall.net/projects/yasm/releases/yasm-${YASM_VERSION}.tar.gz && \ 88 | tar -xf yasm-${YASM_VERSION}.tar.gz && \ 89 | cd yasm-${YASM_VERSION} && \ 90 | ./configure --prefix="/ffmpeg_build" --bindir="$HOME/bin" && \ 91 | make -j$(getconf _NPROCESSORS_ONLN) && \ 92 | make install && \ 93 | cd .. && \ 94 | rm -rf ~/yasm_sources 95 | 96 | RUN mkdir ~/libvpx_sources && \ 97 | cd ~/libvpx_sources && \ 98 | git clone --depth 1 -b ${VPX_VERSION} https://chromium.googlesource.com/webm/libvpx.git && \ 99 | cd libvpx && \ 100 | ./configure --prefix="/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 101 | make -j$(getconf _NPROCESSORS_ONLN) && \ 102 | make install && \ 103 | cd .. && \ 104 | rm -rf ~/libvpx_sources 105 | 106 | RUN mkdir ~/aom_sources && \ 107 | cd ~/aom_sources && \ 108 | git clone --depth 1 -b ${AOM_VERSION} https://aomedia.googlesource.com/aom && \ 109 | mkdir build && cd build && \ 110 | cmake -DCMAKE_C_COMPILER=$(dirname $(which g++))/gcc -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=ON -DENABLE_TESTS=OFF ../aom/ && \ 111 | make -j$(getconf _NPROCESSORS_ONLN) && \ 112 | make install && \ 113 | cd / && rm -rf ~/aom_sources 114 | 115 | RUN mkdir ~/avif_sources && \ 116 | cd ~/avif_sources && \ 117 | git clone -b ${AVIF_VERSION} https://github.com/AOMediaCodec/libavif.git && \ 118 | mkdir build && cd build && \ 119 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DAVIF_CODEC_AOM=SYSTEM -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_APPS=OFF ../libavif && \ 120 | make -j$(getconf _NPROCESSORS_ONLN) && \ 121 | make install && \ 122 | cd / && rm -rf ~/avif_sources 123 | 124 | RUN mkdir ~/ffmpeg_sources && \ 125 | cd ~/ffmpeg_sources && \ 126 | curl -O -L https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 127 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 128 | cd ffmpeg-${FFMPEG_VERSION} && \ 129 | PATH=~/bin:$PATH && \ 130 | PKG_CONFIG_PATH="/ffmpeg_build/lib/pkgconfig" ./configure --prefix="/ffmpeg_build" --extra-cflags="-I/ffmpeg_build/include" --extra-ldflags="-L/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 131 | make -j$(getconf _NPROCESSORS_ONLN) && \ 132 | make install && \ 133 | echo "/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 134 | ldconfig && \ 135 | rm -rf ~/ffmpeg_sources 136 | 137 | RUN curl -O -L https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz && \ 138 | tar -xf ccache-${CCACHE_VERSION}.tar.gz && \ 139 | cd ccache-${CCACHE_VERSION} && \ 140 | ./configure && \ 141 | make -j$(getconf _NPROCESSORS_ONLN) && \ 142 | make install && \ 143 | cd .. && \ 144 | rm -rf ccache-${CCACHE_VERSION}.tar.gz 145 | 146 | # GitHub Actions user`s UID is 1001 147 | RUN useradd ci -m -s /bin/bash -G users --uid=1001 && \ 148 | mkdir /io && \ 149 | chown -R ci:ci /io && \ 150 | # This needs to find ffmpeg packages from ci user 151 | chown -R ci:ci /ffmpeg_build && \ 152 | # This calls in mutlibuild scripts and cannot be run without permissions 153 | chown -R ci:ci /opt/_internal/pipx/venvs/auditwheel 154 | 155 | USER ci 156 | 157 | # Git security vulnerability: https://github.blog/2022-04-12-git-security-vulnerability-announced 158 | RUN git config --global --add safe.directory /io 159 | 160 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/ffmpeg_build/lib/pkgconfig 161 | ENV LDFLAGS -L/ffmpeg_build/lib 162 | ENV PATH "$HOME/bin:$PATH" 163 | -------------------------------------------------------------------------------- /docker/manylinux2014/Dockerfile_aarch64: -------------------------------------------------------------------------------- 1 | # Version: 20250630 2 | # Image name: quay.io/opencv-ci/opencv-python-manylinux2014-aarch64 3 | 4 | FROM quay.io/pypa/manylinux2014_aarch64:latest 5 | 6 | ARG CCACHE_VERSION=3.7.9 7 | ARG FFMPEG_VERSION=5.1.6 8 | ARG FREETYPE_VERSION=2.13.3 9 | ARG LIBPNG_VERSION=1.6.48 10 | ARG VPX_VERSION=v1.15.1 11 | ARG NASM_VERSION=2.15.04 12 | ARG OPENSSL_VERSION=1_1_1w 13 | ARG QT_VERSION=5.15.16 14 | ARG YASM_VERSION=1.3.0 15 | ARG AOM_VERSION=v3.12.1 16 | ARG AVIF_VERSION=v1.3.0 17 | 18 | ENV LD_LIBRARY_PATH /usr/local/lib:$LD_LIBRARY_PATH 19 | 20 | # epel-release need for aarch64 to get openblas packages 21 | RUN yum install zlib-devel curl-devel xcb-util-renderutil-devel xcb-util-devel xcb-util-image-devel xcb-util-keysyms-devel xcb-util-wm-devel mesa-libGL-devel libxkbcommon-devel libxkbcommon-x11-devel libXi-devel lapack-devel epel-release -y && \ 22 | yum install openblas-devel dejavu-sans-fonts -y && \ 23 | cp /usr/include/lapacke/lapacke*.h /usr/include/ && \ 24 | cp /usr/include/openblas/*.h /usr/include/ && \ 25 | # libpng will be built from source 26 | yum remove libpng -y 27 | 28 | RUN mkdir ~/libpng_sources && \ 29 | cd ~/libpng_sources && \ 30 | curl -O -L https://download.sourceforge.net/libpng/libpng-${LIBPNG_VERSION}.tar.gz && \ 31 | tar -xf libpng-${LIBPNG_VERSION}.tar.gz && \ 32 | cd libpng-${LIBPNG_VERSION} && \ 33 | ./configure --prefix=/usr/local && \ 34 | make && \ 35 | make install && \ 36 | cd .. && \ 37 | rm -rf ~/libpng_sources 38 | 39 | # looks like download.savannah.gnu.org suffers from https://savannah.gnu.org/bugs/?48150 in Manylinux 2014 env on aarch64 40 | RUN mkdir ~/freetype_sources && \ 41 | cd ~/freetype_sources && \ 42 | curl -O -L https://download-mirror.savannah.gnu.org/releases/freetype/freetype-${FREETYPE_VERSION}.tar.gz && \ 43 | tar -xf freetype-${FREETYPE_VERSION}.tar.gz && \ 44 | cd freetype-${FREETYPE_VERSION} && \ 45 | ./configure --prefix="/ffmpeg_build" --enable-freetype-config && \ 46 | make && \ 47 | make install && \ 48 | cd .. && \ 49 | rm -rf ~/freetype_sources 50 | 51 | RUN curl -C - -O -L https://download.qt.io/archive/qt/5.15/${QT_VERSION}/single/qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 52 | tar -xf qt-everywhere-opensource-src-${QT_VERSION}.tar.xz && \ 53 | cd qt-everywhere-src-${QT_VERSION} && \ 54 | export MAKEFLAGS=-j$(nproc) && \ 55 | ./configure -prefix /opt/Qt${QT_VERSION} -release -opensource -confirm-license -qtnamespace QtOpenCVPython -xcb -xcb-xlib -bundled-xcb-xinput -no-openssl -no-dbus -skip qt3d -skip qtactiveqt -skip qtcanvas3d -skip qtconnectivity -skip qtdatavis3d -skip qtdoc -skip qtgamepad -skip qtgraphicaleffects -skip qtimageformats -skip qtlocation -skip qtmultimedia -skip qtpurchasing -skip qtqa -skip qtremoteobjects -skip qtrepotools -skip qtscript -skip qtscxml -skip qtsensors -skip qtserialbus -skip qtserialport -skip qtspeech -skip qttranslations -skip qtwayland -skip qtwebchannel -skip qtwebengine -skip qtwebsockets -skip qtwebview -skip xmlpatterns -skip declarative -make libs && \ 56 | make && \ 57 | make install && \ 58 | cd .. && \ 59 | rm -rf qt-everywhere* 60 | 61 | ENV QTDIR /opt/Qt${QT_VERSION} 62 | ENV PATH "$QTDIR/bin:$PATH" 63 | 64 | RUN mkdir ~/openssl_sources && \ 65 | cd ~/openssl_sources && \ 66 | curl -O -L https://github.com/openssl/openssl/archive/OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 67 | tar -xf OpenSSL_${OPENSSL_VERSION}.tar.gz && \ 68 | cd openssl-OpenSSL_${OPENSSL_VERSION} && \ 69 | ./config --prefix="/ffmpeg_build" --openssldir="/ffmpeg_build" no-pinshared shared zlib && \ 70 | make -j$(getconf _NPROCESSORS_ONLN) && \ 71 | # skip installing documentation 72 | make install_sw && \ 73 | cd .. && \ 74 | rm -rf ~/openssl_build ~/openssl_sources 75 | 76 | RUN mkdir ~/nasm_sources && \ 77 | cd ~/nasm_sources && \ 78 | curl -O -L http://www.nasm.us/pub/nasm/releasebuilds/${NASM_VERSION}/nasm-${NASM_VERSION}.tar.gz && \ 79 | tar -xf nasm-${NASM_VERSION}.tar.gz && cd nasm-${NASM_VERSION} && ./autogen.sh && \ 80 | ./configure --prefix="/ffmpeg_build" --bindir="$HOME/bin" && \ 81 | make -j$(getconf _NPROCESSORS_ONLN) && \ 82 | make install && \ 83 | cd .. && \ 84 | rm -rf ~/nasm_sources 85 | 86 | RUN mkdir ~/yasm_sources && \ 87 | cd ~/yasm_sources && \ 88 | curl -O -L http://www.tortall.net/projects/yasm/releases/yasm-${YASM_VERSION}.tar.gz && \ 89 | tar -xf yasm-${YASM_VERSION}.tar.gz && \ 90 | cd yasm-${YASM_VERSION} && \ 91 | ./configure --prefix="/ffmpeg_build" --bindir="$HOME/bin" && \ 92 | make -j$(getconf _NPROCESSORS_ONLN) && \ 93 | make install && \ 94 | cd .. && \ 95 | rm -rf ~/yasm_sources 96 | 97 | RUN mkdir ~/libvpx_sources && \ 98 | cd ~/libvpx_sources && \ 99 | git clone --depth 1 -b ${VPX_VERSION} https://github.com/webmproject/libvpx.git && \ 100 | cd libvpx && \ 101 | ./configure --prefix="/ffmpeg_build" --disable-examples --disable-unit-tests --enable-vp9-highbitdepth --as=yasm --enable-pic --enable-shared && \ 102 | make -j$(getconf _NPROCESSORS_ONLN) && \ 103 | make install && \ 104 | cd .. && \ 105 | rm -rf ~/libvpx_sources 106 | 107 | RUN mkdir ~/aom_sources && \ 108 | cd ~/aom_sources && \ 109 | git clone --depth 1 -b ${AOM_VERSION} https://aomedia.googlesource.com/aom && \ 110 | mkdir build && cd build && \ 111 | cmake -DCMAKE_C_COMPILER=$(dirname $(which g++))/gcc -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=ON -DENABLE_TESTS=OFF ../aom/ && \ 112 | make -j$(getconf _NPROCESSORS_ONLN) && \ 113 | make install && \ 114 | cd / && rm -rf ~/aom_sources 115 | 116 | RUN mkdir ~/avif_sources && \ 117 | cd ~/avif_sources && \ 118 | git clone -b ${AVIF_VERSION} https://github.com/AOMediaCodec/libavif.git && \ 119 | mkdir build && cd build && \ 120 | cmake -DCMAKE_INSTALL_PREFIX=/usr -DAVIF_CODEC_AOM=SYSTEM -DAVIF_LIBYUV=LOCAL -DAVIF_BUILD_APPS=OFF ../libavif && \ 121 | make -j$(getconf _NPROCESSORS_ONLN) && \ 122 | make install && \ 123 | cd / && rm -rf ~/avif_sources 124 | 125 | RUN mkdir ~/ffmpeg_sources && \ 126 | cd ~/ffmpeg_sources && \ 127 | curl -O -L https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 128 | tar -xf ffmpeg-${FFMPEG_VERSION}.tar.gz && \ 129 | cd ffmpeg-${FFMPEG_VERSION} && \ 130 | PATH=~/bin:$PATH && \ 131 | PKG_CONFIG_PATH="/ffmpeg_build/lib/pkgconfig" ./configure --prefix="/ffmpeg_build" --extra-cflags="-I/ffmpeg_build/include" --extra-ldflags="-L/ffmpeg_build/lib" --enable-openssl --enable-libvpx --enable-shared --enable-pic --bindir="$HOME/bin" && \ 132 | make -j$(getconf _NPROCESSORS_ONLN) && \ 133 | make install && \ 134 | echo "/ffmpeg_build/lib/" >> /etc/ld.so.conf && \ 135 | ldconfig && \ 136 | rm -rf ~/ffmpeg_sources 137 | 138 | RUN curl -O -L https://github.com/ccache/ccache/releases/download/v${CCACHE_VERSION}/ccache-${CCACHE_VERSION}.tar.gz && \ 139 | tar -xf ccache-${CCACHE_VERSION}.tar.gz && \ 140 | cd ccache-${CCACHE_VERSION} && \ 141 | linux32 ./configure && \ 142 | make -j$(getconf _NPROCESSORS_ONLN) && \ 143 | make install && \ 144 | cd .. && \ 145 | rm -rf ccache-${CCACHE_VERSION}.tar.gz 146 | 147 | # Self-hosted runner UID is 1004 148 | RUN useradd ci -m -s /bin/bash -G users --uid=1004 && \ 149 | mkdir /io && \ 150 | chown -R ci:ci /io && \ 151 | # This needs to find ffmpeg packages from ci user 152 | chown -R ci:ci /ffmpeg_build && \ 153 | # This calls in mutlibuild scripts and cannot be run without permissions 154 | chown -R ci:ci /opt/_internal/pipx/venvs/auditwheel 155 | 156 | USER ci 157 | 158 | # Git security vulnerability: https://github.blog/2022-04-12-git-security-vulnerability-announced 159 | RUN git config --global --add safe.directory /io 160 | 161 | ENV PKG_CONFIG_PATH /usr/local/lib/pkgconfig:/ffmpeg_build/lib/pkgconfig 162 | ENV LDFLAGS -L/ffmpeg_build/lib 163 | ENV PATH "$HOME/bin:$PATH" 164 | -------------------------------------------------------------------------------- /.github/workflows/build_wheels_macos_m1.yml: -------------------------------------------------------------------------------- 1 | name: macOS ARM64 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 4.x 7 | - 5.x 8 | paths-ignore: 9 | - '.github/workflows/build_wheels_manylinux*' 10 | - '.github/workflows/build_wheels_windows*' 11 | - '.github/workflows/build_wheels_macos.yml' 12 | release: 13 | types: [published, edited] 14 | schedule: 15 | - cron: '0 3 * * 6' 16 | workflow_dispatch: 17 | 18 | 19 | jobs: 20 | Build: 21 | runs-on: python-macos12-m1 22 | strategy: 23 | fail-fast: false 24 | matrix: 25 | python-version: ['3.9'] 26 | platform: [x64] 27 | with_contrib: [0, 1] 28 | without_gui: [0, 1] 29 | build_sdist: [0] 30 | env: 31 | CI_BUILD: 1 32 | SDIST: ${{ matrix.build_sdist || 0 }} 33 | ENABLE_HEADLESS: ${{ matrix.without_gui }} 34 | ENABLE_CONTRIB: ${{ matrix.with_contrib }} 35 | PIP_INDEX_URL: https://pypi.tuna.tsinghua.edu.cn/simple 36 | steps: 37 | - name: Cleanup 38 | run: find . -mindepth 1 -delete 39 | working-directory: ${{ github.workspace }} 40 | - name: Setup environment 41 | run: | 42 | if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then 43 | echo "ENABLE_ROLLING=1" >> $GITHUB_ENV 44 | fi 45 | - name: Checkout 46 | uses: actions/checkout@v3 47 | with: 48 | submodules: false 49 | fetch-depth: 0 50 | - name: Build a package 51 | run: | 52 | git submodule update --init multibuild 53 | echo $ENABLE_CONTRIB > contrib.enabled 54 | echo $ENABLE_HEADLESS > headless.enabled 55 | export MACOSX_DEPLOYMENT_TARGET=13.0 56 | python${{ matrix.python-version }} -m pip install toml && python${{ matrix.python-version }} -c 'import toml; c = toml.load("pyproject.toml"); print("\n".join(c["build-system"]["requires"]))' | python${{ matrix.python-version }} -m pip install -r /dev/stdin 57 | python${{ matrix.python-version }} setup.py bdist_wheel --py-limited-api=cp37 --dist-dir=wheelhouse -v 58 | delocate-wheel ${{ github.workspace }}/wheelhouse/opencv* 59 | - name: Saving a wheel accordingly to matrix 60 | uses: actions/upload-artifact@v4 61 | with: 62 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 63 | path: wheelhouse/opencv*.whl 64 | 65 | Test: 66 | needs: [Build] 67 | runs-on: python-macos12-m1 68 | strategy: 69 | fail-fast: false 70 | matrix: 71 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 72 | platform: [x64] 73 | with_contrib: [0, 1] 74 | without_gui: [0, 1] 75 | build_sdist: [0] 76 | env: 77 | OPENCV_TEST_DATA_PATH: ${{ github.workspace }}/opencv_extra/testdata 78 | PYLINT_TEST_FILE: ${{ github.workspace }}/opencv/samples/python/squares.py 79 | PIP_INDEX_URL: https://pypi.tuna.tsinghua.edu.cn/simple 80 | steps: 81 | - name: Cleanup 82 | run: find . -mindepth 1 -delete 83 | working-directory: ${{ github.workspace }} 84 | - name: Checkout 85 | uses: actions/checkout@v3 86 | with: 87 | submodules: true 88 | fetch-depth: 0 89 | - name: Download a wheel accordingly to matrix 90 | uses: actions/download-artifact@v4 91 | with: 92 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 93 | path: wheelhouse/ 94 | - name: Create Venv for test 95 | run: | 96 | test -d "${{ github.workspace }}/opencv_test" && rm -rf "${{ github.workspace }}/opencv_test" 97 | python${{ matrix.python-version }} -m venv ${{ github.workspace }}/opencv_test 98 | - name: Package installation 99 | run: | 100 | source ${{ github.workspace }}/opencv_test/bin/activate 101 | python${{ matrix.python-version }} -m pip install --upgrade pip 102 | python${{ matrix.python-version }} -m pip install --no-cache --force-reinstall wheelhouse/opencv*.whl 103 | cd ${{ github.workspace }}/tests 104 | python${{ matrix.python-version }} get_build_info.py 105 | - name: Run tests 106 | run: | 107 | source ${{ github.workspace }}/opencv_test/bin/activate 108 | cd ${{ github.workspace }}/opencv 109 | python${{ matrix.python-version }} modules/python/test/test.py -v --repo . 110 | - name: Pylint test 111 | run: | 112 | source ${{ github.workspace }}/opencv_test/bin/activate 113 | python${{ matrix.python-version }} -m pip install pylint==2.15.9 114 | cd ${{ github.workspace }}/tests 115 | python${{ matrix.python-version }} -m pylint $PYLINT_TEST_FILE 116 | 117 | Release_rolling: 118 | if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} 119 | needs: [Build, Test] 120 | runs-on: ubuntu-22.04 121 | environment: opencv-python-rolling-release 122 | defaults: 123 | run: 124 | shell: bash 125 | steps: 126 | - uses: actions/download-artifact@v4 127 | with: 128 | name: wheels 129 | path: wheelhouse/ 130 | - name: Upload wheels for opencv_python_rolling 131 | run: | 132 | python -m pip install twine 133 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_python_rolling-* 134 | - name: Upload wheels for opencv_contrib_python_rolling 135 | run: | 136 | python -m pip install twine 137 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_rolling-* 138 | - name: Upload wheels for opencv_python_headless_rolling 139 | run: | 140 | python -m pip install twine 141 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_python_headless_rolling-* 142 | - name: Upload wheels for opencv_contrib_python_headless_rolling 143 | run: | 144 | python -m pip install twine 145 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_headless_rolling-* 146 | 147 | Pre-release: 148 | if: github.event_name == 'release' && github.event.release.prerelease 149 | needs: [Build, Test] 150 | runs-on: ubuntu-22.04 151 | environment: test-opencv-python-release 152 | defaults: 153 | run: 154 | shell: bash 155 | steps: 156 | - uses: actions/download-artifact@v4 157 | with: 158 | name: wheels 159 | path: wheelhouse/ 160 | - name: Upload all wheels 161 | run: | 162 | python -m pip install twine 163 | python -m twine upload --repository testpypi -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --skip-existing wheelhouse/opencv_* 164 | 165 | Release: 166 | if: github.event_name == 'release' && !github.event.release.prerelease 167 | needs: [Build, Test] 168 | runs-on: ubuntu-22.04 169 | environment: opencv-python-release 170 | defaults: 171 | run: 172 | shell: bash 173 | steps: 174 | - uses: actions/download-artifact@v4 175 | with: 176 | name: wheels 177 | path: wheelhouse/ 178 | - name: Upload wheels for opencv_python 179 | run: | 180 | python -m pip install twine 181 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_PASSWORD }} --skip-existing wheelhouse/opencv_python-* 182 | - name: Upload wheels for opencv_contrib_python 183 | run: | 184 | python -m pip install twine 185 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python-* 186 | - name: Upload wheels for opencv_python_headless 187 | run: | 188 | python -m pip install twine 189 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/opencv_python_headless-* 190 | - name: Upload wheels for opencv_contrib_python_headless 191 | run: | 192 | python -m pip install twine 193 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_headless-* 194 | -------------------------------------------------------------------------------- /.github/workflows/build_wheels_windows.yml: -------------------------------------------------------------------------------- 1 | name: Windows x86_64 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 4.x 7 | - 5.x 8 | paths-ignore: 9 | - '.github/workflows/build_wheels_manylinux*' 10 | - '.github/workflows/build_wheels_macos*' 11 | release: 12 | types: [published, edited] 13 | schedule: 14 | - cron: '0 3 * * 6' 15 | workflow_dispatch: 16 | 17 | 18 | jobs: 19 | Build: 20 | runs-on: windows-2025 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | python-version: ['3.9'] 25 | platform: [x86, x64] 26 | with_contrib: [0, 1] 27 | without_gui: [0, 1] 28 | build_sdist: [0] 29 | env: 30 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 31 | SDIST: ${{ matrix.build_sdist || 0 }} 32 | ENABLE_HEADLESS: ${{ matrix.without_gui }} 33 | ENABLE_CONTRIB: ${{ matrix.with_contrib }} 34 | OPENCV_TEST_DATA_PATH: ${{ github.workspace }}\opencv_extra\testdata 35 | steps: 36 | - name: Cleanup 37 | shell: bash 38 | run: | 39 | rm -rf ./* || true 40 | rm -rf ./.??* || true 41 | working-directory: ${{ github.workspace }} 42 | - name: Setup environment 43 | shell: bash 44 | run: | 45 | if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then 46 | echo "ENABLE_ROLLING=1" >> $GITHUB_ENV 47 | fi 48 | - name: Checkout 49 | uses: actions/checkout@v4 50 | with: 51 | submodules: false 52 | fetch-depth: 0 53 | - name: Set up Python ${{ matrix.python-version }} 54 | uses: actions/setup-python@v4 55 | with: 56 | python-version: ${{ matrix.python-version }} 57 | architecture: ${{ matrix.platform }} 58 | - name: Setup MSBuild.exe 59 | uses: microsoft/setup-msbuild@v1.1 60 | - name: Setup NASM 61 | uses: ilammy/setup-nasm@v1 62 | - name: Build a package 63 | # CMake 3.25 regression fix. See https://stackoverflow.com/questions/74162633/problem-compiling-from-source-opencv-with-mvsc2019-in-64-bit-version 64 | run: | 65 | python --version 66 | python -m pip install --upgrade pip 67 | python -m pip install --upgrade setuptools 68 | python -m pip install cmake==3.24.2 69 | python -m pip install toml && python -c "import toml; c = toml.load('pyproject.toml'); print('\n'.join(c['build-system']['requires']))" >> requirements.txt | python -m pip install -r requirements.txt 70 | set "CI_BUILD=1" && python setup.py bdist_wheel --py-limited-api=cp37 --dist-dir=%cd%\wheelhouse -v 71 | shell: cmd 72 | - name: Saving all wheels 73 | uses: actions/upload-artifact@v4 74 | with: 75 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }}-${{ matrix.platform }} 76 | path: wheelhouse/opencv* 77 | 78 | Test: 79 | needs: [Build] 80 | runs-on: windows-2025 81 | defaults: 82 | run: 83 | shell: cmd 84 | strategy: 85 | fail-fast: false 86 | matrix: 87 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 88 | platform: [x86, x64] 89 | with_contrib: [0, 1] 90 | without_gui: [0, 1] 91 | build_sdist: [0] 92 | env: 93 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 94 | OPENCV_TEST_DATA_PATH: ${{ github.workspace }}\opencv_extra\testdata 95 | PYLINT_TEST_FILE: ${{ github.workspace }}\opencv\samples\python\squares.py 96 | PlatformToolset: v143 97 | steps: 98 | - name: Cleanup 99 | shell: bash 100 | run: | 101 | rm -rf ./* || true 102 | rm -rf ./.??* || true 103 | working-directory: ${{ github.workspace }} 104 | - name: Checkout 105 | uses: actions/checkout@v4 106 | with: 107 | submodules: true 108 | fetch-depth: 0 109 | - name: Set up Python ${{ matrix.python-version }} 110 | uses: actions/setup-python@v4 111 | with: 112 | python-version: ${{ matrix.python-version }} 113 | architecture: ${{ matrix.platform }} 114 | - name: Download a wheel accordingly to matrix 115 | uses: actions/download-artifact@v4 116 | with: 117 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }}-${{ matrix.platform }} 118 | path: wheelhouse/ 119 | - name: Package installation 120 | run: | 121 | cd ${{ github.workspace }}/tests 122 | &python -m pip install --user --no-warn-script-location (ls "../wheelhouse/opencv*.whl") 123 | if ($LastExitCode -ne 0) {throw $LastExitCode} 124 | python get_build_info.py 125 | shell: powershell 126 | - name: Run tests 127 | run: | 128 | cd ${{ github.workspace }}/opencv 129 | python modules\python\test\test.py -v --repo . 130 | - name: Pylint test 131 | run: | 132 | python -m pip install pylint==2.15.9 133 | cd ${{ github.workspace }}\tests 134 | python -m pylint $PYLINT_TEST_FILE 135 | 136 | Release_rolling: 137 | if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} 138 | needs: [Build, Test] 139 | runs-on: ubuntu-22.04 140 | environment: opencv-python-rolling-release 141 | defaults: 142 | run: 143 | shell: bash 144 | steps: 145 | - uses: actions/download-artifact@v4 146 | with: 147 | path: wheelhouse/ 148 | - name: Upload wheels for opencv_python_rolling 149 | run: | 150 | python -m pip install twine 151 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_python_rolling-* 152 | - name: Upload wheels for opencv_contrib_python_rolling 153 | run: | 154 | python -m pip install twine 155 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_rolling-* 156 | - name: Upload wheels for opencv_python_headless_rolling 157 | run: | 158 | python -m pip install twine 159 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_python_headless_rolling-* 160 | - name: Upload wheels for opencv_contrib_python_headless_rolling 161 | run: | 162 | python -m pip install twine 163 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_headless_rolling-* 164 | 165 | Pre-release: 166 | if: github.event_name == 'release' && github.event.release.prerelease 167 | needs: [Build, Test] 168 | runs-on: ubuntu-22.04 169 | environment: test-opencv-python-release 170 | defaults: 171 | run: 172 | shell: bash 173 | steps: 174 | - uses: actions/download-artifact@v4 175 | with: 176 | path: wheelhouse/ 177 | - name: Upload all wheels 178 | run: | 179 | python -m pip install twine 180 | python -m twine upload --repository testpypi -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --skip-existing wheelhouse/opencv_* 181 | 182 | Release: 183 | if: github.event_name == 'release' && !github.event.release.prerelease 184 | needs: [Build, Test] 185 | runs-on: ubuntu-22.04 186 | environment: opencv-python-release 187 | defaults: 188 | run: 189 | shell: bash 190 | steps: 191 | - uses: actions/download-artifact@v4 192 | with: 193 | path: wheelhouse/ 194 | - name: Upload wheels for opencv_python 195 | run: | 196 | python -m pip install twine 197 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_PASSWORD }} --skip-existing wheelhouse/opencv_python-* 198 | - name: Upload wheels for opencv_contrib_python 199 | run: | 200 | python -m pip install twine 201 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python-* 202 | - name: Upload wheels for opencv_python_headless 203 | run: | 204 | python -m pip install twine 205 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/opencv_python_headless-* 206 | - name: Upload wheels for opencv_contrib_python_headless 207 | run: | 208 | python -m pip install twine 209 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_headless-* 210 | -------------------------------------------------------------------------------- /.github/workflows/build_wheels_macos.yml: -------------------------------------------------------------------------------- 1 | name: macOS x86_64 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 4.x 7 | - 5.x 8 | paths-ignore: 9 | - '.github/workflows/build_wheels_manylinux*' 10 | - '.github/workflows/build_wheels_windows*' 11 | - '.github/workflows/build_wheels_macos_m1.yml' 12 | release: 13 | types: [published, edited] 14 | schedule: 15 | - cron: '0 3 * * 6' 16 | workflow_dispatch: 17 | 18 | 19 | jobs: 20 | Build: 21 | runs-on: macos-13 22 | defaults: 23 | run: 24 | shell: bash 25 | strategy: 26 | fail-fast: false 27 | matrix: 28 | python-version: ['3.9'] 29 | platform: [x64] 30 | with_contrib: [0, 1] 31 | without_gui: [0, 1] 32 | build_sdist: [0] 33 | env: 34 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 35 | REPO_DIR: . 36 | PROJECT_SPEC: opencv-python 37 | MB_PYTHON_VERSION: ${{ matrix.python-version }} 38 | TRAVIS_PYTHON_VERSION: ${{ matrix.python-version }} 39 | MB_ML_VER: 2014 40 | TRAVIS_BUILD_DIR: ${{ github.workspace }} 41 | TRAVIS_OS_NAME: osx 42 | CONFIG_PATH: travis_config.sh 43 | USE_CCACHE: 1 44 | UNICODE_WIDTH: 32 45 | PLAT: x86_64 46 | SDIST: ${{ matrix.build_sdist || 0 }} 47 | ENABLE_HEADLESS: ${{ matrix.without_gui }} 48 | ENABLE_CONTRIB: ${{ matrix.with_contrib }} 49 | steps: 50 | - name: Cleanup 51 | run: find . -mindepth 1 -delete 52 | working-directory: ${{ github.workspace }} 53 | - name: Setup environment 54 | run: | 55 | if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then 56 | echo "ENABLE_ROLLING=1" >> $GITHUB_ENV 57 | fi 58 | # hack for image issue on mac: https://github.com/actions/runner-images/issues/6817 59 | rm /usr/local/bin/2to3* 60 | rm /usr/local/bin/idle3* 61 | rm /usr/local/bin/pydoc3* 62 | rm /usr/local/bin/python3* 63 | # end hack 64 | - name: Checkout 65 | uses: actions/checkout@v3 66 | with: 67 | submodules: false 68 | fetch-depth: 0 69 | - name: Build a package 70 | run: | 71 | set -e 72 | # Check out and prepare the source 73 | # Multibuild doesn't have releases, so --depth would break eventually (see 74 | # https://superuser.com/questions/1240216/server-does-not-allow-request-for-unadvertised) 75 | git submodule update --init multibuild 76 | source multibuild/common_utils.sh 77 | # https://github.com/matthew-brett/multibuild/issues/116 78 | if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export ARCH_FLAGS=" "; fi 79 | source multibuild/travis_steps.sh 80 | # This sets -x 81 | # source travis_multibuild_customize.sh 82 | echo $ENABLE_CONTRIB > contrib.enabled 83 | echo $ENABLE_HEADLESS > headless.enabled 84 | set -x 85 | build_wheel $REPO_DIR $PLAT 86 | - name: Saving a wheel accordingly to matrix 87 | uses: actions/upload-artifact@v4 88 | with: 89 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 90 | path: wheelhouse/opencv*.whl 91 | 92 | Test: 93 | needs: [Build] 94 | runs-on: macos-13 95 | defaults: 96 | run: 97 | shell: bash 98 | strategy: 99 | fail-fast: false 100 | matrix: 101 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 102 | platform: [x64] 103 | with_contrib: [0, 1] 104 | without_gui: [0, 1] 105 | build_sdist: [0] 106 | env: 107 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 108 | MB_PYTHON_VERSION: ${{ matrix.python-version }} 109 | NP_TEST_DEP: numpy==1.19.4 110 | NP_TEST_DEP_LATEST: numpy==2.2.6 111 | CONFIG_PATH: travis_config.sh 112 | PLAT: x86_64 113 | OPENCV_TEST_DATA_PATH: ${{ github.workspace }}/opencv_extra/testdata 114 | PYLINT_TEST_FILE: ${{ github.workspace }}/opencv/samples/python/squares.py 115 | steps: 116 | - name: Cleanup 117 | run: find . -mindepth 1 -delete 118 | working-directory: ${{ github.workspace }} 119 | - name: Checkout 120 | uses: actions/checkout@v3 121 | with: 122 | submodules: true 123 | fetch-depth: 0 124 | - name: Set up Python ${{ matrix.python-version }} 125 | uses: actions/setup-python@v4 126 | with: 127 | python-version: ${{ matrix.python-version }} 128 | architecture: ${{ matrix.platform }} 129 | - name: Setup Environment variables 130 | run: if ["3.10" == "${{ matrix.python-version }}" -o "3.11" == "${{ matrix.python-version }}" -o "3.12" == "${{ matrix.python-version }}" -o "3.13" == "${{ matrix.python-version }}" ]; then echo "TEST_DEPENDS=$(echo $NP_TEST_DEP_LATEST)" >> $GITHUB_ENV; else echo "TEST_DEPENDS=$(echo $NP_TEST_DEP)" >> $GITHUB_ENV; fi 131 | - name: Download a wheel accordingly to matrix 132 | uses: actions/download-artifact@v4 133 | with: 134 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 135 | path: wheelhouse/ 136 | - name: Package installation 137 | run: | 138 | python -m pip install wheelhouse/opencv*.whl 139 | cd ${{ github.workspace }}/tests 140 | python get_build_info.py 141 | - name: Run tests 142 | run: | 143 | cd ${{ github.workspace }}/opencv 144 | python modules/python/test/test.py -v --repo . 145 | - name: Pylint test 146 | run: | 147 | python -m pip install pylint==2.15.9 148 | cd ${{ github.workspace }}/tests 149 | python -m pylint $PYLINT_TEST_FILE 150 | 151 | Release_rolling: 152 | if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} 153 | needs: [Build, Test] 154 | runs-on: ubuntu-22.04 155 | environment: opencv-python-rolling-release 156 | defaults: 157 | run: 158 | shell: bash 159 | steps: 160 | - uses: actions/download-artifact@v4 161 | with: 162 | name: wheels 163 | path: wheelhouse/ 164 | - name: Upload wheels for opencv_python_rolling 165 | run: | 166 | python -m pip install twine 167 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_python_rolling-* 168 | - name: Upload wheels for opencv_contrib_python_rolling 169 | run: | 170 | python -m pip install twine 171 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_rolling-* 172 | - name: Upload wheels for opencv_python_headless_rolling 173 | run: | 174 | python -m pip install twine 175 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_python_headless_rolling-* 176 | - name: Upload wheels for opencv_contrib_python_headless_rolling 177 | run: | 178 | python -m pip install twine 179 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_headless_rolling-* 180 | 181 | Pre-release: 182 | if: github.event_name == 'release' && github.event.release.prerelease 183 | needs: [Build, Test] 184 | runs-on: ubuntu-22.04 185 | environment: test-opencv-python-release 186 | defaults: 187 | run: 188 | shell: bash 189 | steps: 190 | - uses: actions/download-artifact@v4 191 | with: 192 | name: wheels 193 | path: wheelhouse/ 194 | - name: Upload all wheels 195 | run: | 196 | python -m pip install twine 197 | python -m twine upload --repository testpypi -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --skip-existing wheelhouse/opencv_* 198 | 199 | Release: 200 | if: github.event_name == 'release' && !github.event.release.prerelease 201 | needs: [Build, Test] 202 | runs-on: ubuntu-22.04 203 | environment: opencv-python-release 204 | defaults: 205 | run: 206 | shell: bash 207 | steps: 208 | - uses: actions/download-artifact@v4 209 | with: 210 | name: wheels 211 | path: wheelhouse/ 212 | - name: Upload wheels for opencv_python 213 | run: | 214 | python -m pip install twine 215 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_PASSWORD }} --skip-existing wheelhouse/opencv_python-* 216 | - name: Upload wheels for opencv_contrib_python 217 | run: | 218 | python -m pip install twine 219 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python-* 220 | - name: Upload wheels for opencv_python_headless 221 | run: | 222 | python -m pip install twine 223 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/opencv_python_headless-* 224 | - name: Upload wheels for opencv_contrib_python_headless 225 | run: | 226 | python -m pip install twine 227 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/opencv_contrib_python_headless-* 228 | -------------------------------------------------------------------------------- /.github/workflows/build_wheels_manylinux.yml: -------------------------------------------------------------------------------- 1 | name: Manylinux 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - 4.x 7 | - 5.x 8 | paths-ignore: 9 | - '.github/workflows/build_wheels_windows*' 10 | - '.github/workflows/build_wheels_macos*' 11 | release: 12 | types: [published, edited] 13 | schedule: 14 | - cron: '0 3 * * 6' 15 | workflow_dispatch: 16 | 17 | 18 | jobs: 19 | Build: 20 | runs-on: ${{ matrix.platform == 'aarch64' && 'opencv-cn-lin-arm64' || 'ubuntu-22.04' }} 21 | defaults: 22 | run: 23 | shell: bash 24 | strategy: 25 | fail-fast: false 26 | matrix: 27 | python-version: ['3.9'] 28 | platform: [x86_64, aarch64] 29 | manylinux: [2014, 2_28] 30 | with_contrib: [0, 1] 31 | without_gui: [0, 1] 32 | build_sdist: [0] 33 | include: 34 | - platform: aarch64 35 | manylinux: 2014 36 | DOCKER_IMAGE: quay.io/opencv-ci/opencv-python-manylinux2014-aarch64:20250630 37 | - platform: x86_64 38 | manylinux: 2014 39 | DOCKER_IMAGE: quay.io/opencv-ci/opencv-python-manylinux2014-x86-64:20250630 40 | - platform: x86_64 41 | manylinux: 2_28 42 | DOCKER_IMAGE: quay.io/opencv-ci/opencv-python-manylinux_2_28-x86-64:20251013 43 | - platform: aarch64 44 | manylinux: 2_28 45 | DOCKER_IMAGE: quay.io/opencv-ci/opencv-python-manylinux_2_28-aarch64:20251013 46 | 47 | env: 48 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 49 | REPO_DIR: . 50 | PROJECT_SPEC: opencv-python 51 | MB_PYTHON_VERSION: ${{ matrix.python-version }} 52 | TRAVIS_PYTHON_VERSION: ${{ matrix.python-version }} 53 | MB_ML_VER: ${{ matrix.manylinux }} 54 | TRAVIS_BUILD_DIR: ${{ github.workspace }} 55 | CONFIG_PATH: travis_config.sh 56 | DOCKER_IMAGE: ${{ matrix.DOCKER_IMAGE }} 57 | USE_CCACHE: 0 58 | UNICODE_WIDTH: 32 59 | PLAT: ${{ matrix.platform }} 60 | SDIST: ${{ matrix.build_sdist || 0 }} 61 | ENABLE_HEADLESS: ${{ matrix.without_gui }} 62 | ENABLE_CONTRIB: ${{ matrix.with_contrib }} 63 | 64 | steps: 65 | - name: Cleanup 66 | run: find . -mindepth 1 -delete 67 | working-directory: ${{ github.workspace }} 68 | - name: Setup environment 69 | run: | 70 | if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then 71 | echo "ENABLE_ROLLING=1" >> $GITHUB_ENV 72 | fi 73 | - name: Checkout 74 | uses: actions/checkout@v3 75 | with: 76 | submodules: false 77 | fetch-depth: 0 78 | 79 | - name: Build a package 80 | run: source scripts/build.sh 81 | - name: Saving a wheel accordingly to matrix 82 | uses: actions/upload-artifact@v4 83 | with: 84 | name: wheel-${{ matrix.platform }}-${{ matrix.manylinux }}-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 85 | path: wheelhouse/opencv*.whl 86 | 87 | Test: 88 | needs: [Build] 89 | runs-on: ${{ matrix.platform == 'aarch64' && 'opencv-cn-lin-arm64' || 'ubuntu-22.04' }} 90 | defaults: 91 | run: 92 | shell: bash 93 | strategy: 94 | fail-fast: false 95 | matrix: 96 | python-version: ['3.7', '3.8', '3.9', '3.10', '3.11', '3.12', '3.13'] 97 | platform: [x86_64, aarch64] 98 | manylinux: [2014, 2_28] 99 | with_contrib: [0, 1] 100 | without_gui: [0, 1] 101 | build_sdist: [0] 102 | 103 | env: 104 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 105 | MB_PYTHON_VERSION: ${{ matrix.python-version }} 106 | NP_TEST_DEP: numpy==1.19.4 107 | NP_TEST_DEP_LATEST: numpy==2.2.6 108 | CONFIG_PATH: travis_config.sh 109 | PLAT: ${{ matrix.platform }} 110 | SDIST: ${{ matrix.build_sdist || 0 }} 111 | ENABLE_HEADLESS: ${{ matrix.without_gui }} 112 | ENABLE_CONTRIB: ${{ matrix.with_contrib }} 113 | DOCKER_TEST_IMAGE: ${{ matrix.platform == 'aarch64' && 'quay.io/opencv-ci/multibuild-focal_arm64v8:2025-11-13' || '' }} 114 | steps: 115 | - name: Cleanup 116 | run: find . -mindepth 1 -delete 117 | working-directory: ${{ github.workspace }} 118 | - name: Checkout 119 | uses: actions/checkout@v3 120 | with: 121 | submodules: true 122 | fetch-depth: 0 123 | 124 | - name: Setup Environment variables 125 | run: if [ "3.10" == "${{ matrix.python-version }}" -o "3.11" == "${{ matrix.python-version }}" -o "3.12" == "${{ matrix.python-version }}" -o "3.13" == "${{ matrix.python-version }}" ]; then echo "TEST_DEPENDS=$(echo $NP_TEST_DEP_LATEST)" >> $GITHUB_ENV; else echo "TEST_DEPENDS=$(echo $NP_TEST_DEP)" >> $GITHUB_ENV; fi 126 | - name: Download a wheel accordingly to matrix 127 | uses: actions/download-artifact@v4 128 | with: 129 | name: wheel-${{ matrix.platform }}-${{ matrix.manylinux }}-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 130 | path: wheelhouse/ 131 | - name: Package installation and run tests 132 | run: source scripts/install.sh 133 | 134 | Build_sdist: 135 | runs-on: ubuntu-22.04 136 | defaults: 137 | run: 138 | shell: bash 139 | strategy: 140 | fail-fast: false 141 | matrix: 142 | python-version: [3.8] 143 | platform: [x64] 144 | with_contrib: [0, 1] 145 | without_gui: [0, 1] 146 | build_sdist: [1] 147 | env: 148 | ACTIONS_ALLOW_UNSECURE_COMMANDS: true 149 | REPO_DIR: . 150 | PROJECT_SPEC: opencv-python 151 | PLAT: x86_64 152 | MB_PYTHON_VERSION: ${{ matrix.python-version }} 153 | TRAVIS_PYTHON_VERSION: ${{ matrix.python-version }} 154 | MB_ML_VER: 2014 155 | NP_TEST_DEP: numpy==1.19.4 156 | TRAVIS_BUILD_DIR: ${{ github.workspace }} 157 | CONFIG_PATH: travis_config.sh 158 | DOCKER_IMAGE: quay.io/opencv-ci/opencv-python-manylinux2014-x86-64:20250630 159 | USE_CCACHE: 1 160 | UNICODE_WIDTH: 32 161 | SDIST: ${{ matrix.build_sdist || 0 }} 162 | ENABLE_HEADLESS: ${{ matrix.without_gui || 0 }} 163 | ENABLE_CONTRIB: ${{ matrix.with_contrib || 0 }} 164 | steps: 165 | - name: Cleanup 166 | run: find . -mindepth 1 -delete 167 | working-directory: ${{ github.workspace }} 168 | - name: Setup environment 169 | run: | 170 | if [[ "${{ github.event_name }}" == "schedule" || "${{ github.event_name }}" == "workflow_dispatch" ]]; then 171 | echo "ENABLE_ROLLING=1" >> $GITHUB_ENV 172 | fi 173 | - name: Checkout 174 | uses: actions/checkout@v3 175 | with: 176 | submodules: false 177 | fetch-depth: 0 178 | - name: Set up Python ${{ matrix.python-version }} 179 | uses: actions/setup-python@v4 180 | with: 181 | python-version: ${{ matrix.python-version }} 182 | architecture: ${{ matrix.platform }} 183 | - name: Build a package 184 | run: | 185 | set -e 186 | # Build and package 187 | set -x 188 | python -m pip install --upgrade pip 189 | python -m pip install scikit-build 190 | python setup.py sdist --formats=gztar 191 | set +x 192 | # Install and run tests 193 | set -x 194 | echo "skipping tests because of sdist" 195 | - name: saving artifacts 196 | uses: actions/upload-artifact@v4 197 | with: 198 | name: wheel-${{ matrix.with_contrib }}-${{ matrix.without_gui }}-${{ matrix.build_sdist }} 199 | path: dist/opencv*.tar.gz 200 | 201 | Release_rolling: 202 | if: ${{ github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' }} 203 | needs: [Build, Test] 204 | runs-on: ubuntu-22.04 205 | environment: opencv-python-rolling-release 206 | defaults: 207 | run: 208 | shell: bash 209 | steps: 210 | - uses: actions/download-artifact@v4 211 | with: 212 | path: wheelhouse/ 213 | 214 | - name: Upload wheels for opencv_python_rolling 215 | run: | 216 | python -m pip install twine 217 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_python_rolling-* 218 | - name: Upload wheels for opencv_contrib_python_rolling 219 | run: | 220 | python -m pip install twine 221 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_ROLLING_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_contrib_python_rolling-* 222 | - name: Upload wheels for opencv_python_headless_rolling 223 | run: | 224 | python -m pip install twine 225 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_python_headless_rolling-* 226 | - name: Upload wheels for opencv_contrib_python_headless_rolling 227 | run: | 228 | python -m pip install twine 229 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_ROLLING_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_contrib_python_headless_rolling-* 230 | 231 | Pre-release: 232 | if: github.event_name == 'release' && github.event.release.prerelease 233 | needs: [Build, Build_sdist, Test] 234 | runs-on: ubuntu-22.04 235 | environment: test-opencv-python-release 236 | defaults: 237 | run: 238 | shell: bash 239 | steps: 240 | - uses: actions/download-artifact@v4 241 | with: 242 | path: wheelhouse/ 243 | 244 | - name: Upload all wheels 245 | run: | 246 | python -m pip install twine 247 | python -m twine upload --repository testpypi -u ${{ secrets.PYPI_USERNAME }} -p ${{ secrets.PYPI_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_* wheelhouse/wheel-*/opencv-* 248 | 249 | Release: 250 | if: github.event_name == 'release' && !github.event.release.prerelease 251 | needs: [Build, Build_sdist, Test] 252 | runs-on: ubuntu-22.04 253 | environment: opencv-python-release 254 | defaults: 255 | run: 256 | shell: bash 257 | steps: 258 | - uses: actions/download-artifact@v4 259 | with: 260 | path: wheelhouse/ 261 | - name: Upload wheels for opencv_python 262 | run: | 263 | python -m pip install twine 264 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_python-* wheelhouse/wheel-*/opencv-python-[^h]* 265 | - name: Upload wheels for opencv_contrib_python 266 | run: | 267 | python -m pip install twine 268 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_contrib_python-* wheelhouse/wheel-*/opencv-contrib-python-[^h]* 269 | - name: Upload wheels for opencv_python_headless 270 | run: | 271 | python -m pip install twine 272 | python -m twine upload -u ${{ secrets.OPENCV_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_python_headless-* wheelhouse/wheel-*/opencv-python-headless-* 273 | - name: Upload wheels for opencv_contrib_python_headless 274 | run: | 275 | python -m pip install twine 276 | python -m twine upload -u ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_USERNAME }} -p ${{ secrets.OPENCV_CONTRIB_PYTHON_HEADLESS_PASSWORD }} --skip-existing wheelhouse/wheel-*/opencv_contrib_python_headless-* wheelhouse/wheel-*/opencv-contrib-python-headless-* 277 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Downloads](https://static.pepy.tech/badge/opencv-python)](http://pepy.tech/project/opencv-python) 2 | 3 | ### Keep OpenCV Free 4 | 5 | OpenCV is raising funds to keep the library free for everyone, and we need the support of the entire community to do it. [Donate to OpenCV on Github](https://github.com/sponsors/opencv) to show your support. 6 | 7 | - [OpenCV on Wheels](#opencv-on-wheels) 8 | - [Installation and Usage](#installation-and-usage) 9 | - [Frequently Asked Questions](#frequently-asked-questions) 10 | - [Documentation for opencv-python](#documentation-for-opencv-python) 11 | - [CI build process](#ci-build-process) 12 | - [Manual builds](#manual-builds) 13 | - [Manual debug builds](#manual-debug-builds) 14 | - [Source distributions](#source-distributions) 15 | - [Licensing](#licensing) 16 | - [Versioning](#versioning) 17 | - [Releases](#releases) 18 | - [Development builds](#development-builds) 19 | - [Manylinux wheels](#manylinux-wheels) 20 | - [Supported Python versions](#supported-python-versions) 21 | - [Backward compatibility](#backward-compatibility) 22 | 23 | ## OpenCV on Wheels 24 | 25 | Pre-built CPU-only OpenCV packages for Python. 26 | 27 | Check the manual build section if you wish to compile the bindings from source to enable additional modules such as CUDA. 28 | 29 | ### Installation and Usage 30 | 31 | 1. If you have previous/other manually installed (= not installed via ``pip``) version of OpenCV installed (e.g. cv2 module in the root of Python's site-packages), remove it before installation to avoid conflicts. 32 | 2. Make sure that your `pip` version is up-to-date (19.3 is the minimum supported version): `pip install --upgrade pip`. Check version with `pip -V`. For example Linux distributions ship usually with very old `pip` versions which cause a lot of unexpected problems especially with the `manylinux` format. 33 | 3. Select the correct package for your environment: 34 | 35 | There are four different packages (see options 1, 2, 3 and 4 below) and you should **SELECT ONLY ONE OF THEM**. Do not install multiple different packages in the same environment. There is no plugin architecture: all the packages use the same namespace (`cv2`). If you installed multiple different packages in the same environment, uninstall them all with ``pip uninstall`` and reinstall only one package. 36 | 37 | **a.** Packages for standard desktop environments (Windows, macOS, almost any GNU/Linux distribution) 38 | 39 | - Option 1 - Main modules package: ``pip install opencv-python`` 40 | - Option 2 - Full package (contains both main modules and contrib/extra modules): ``pip install opencv-contrib-python`` (check contrib/extra modules listing from [OpenCV documentation](https://docs.opencv.org/master/)) 41 | 42 | **b.** Packages for server (headless) environments (such as Docker, cloud environments etc.), no GUI library dependencies 43 | 44 | These packages are smaller than the two other packages above because they do not contain any GUI functionality (not compiled with Qt / other GUI components). This means that the packages avoid a heavy dependency chain to X11 libraries and you will have for example smaller Docker images as a result. You should always use these packages if you do not use `cv2.imshow` et al. or you are using some other package (such as PyQt) than OpenCV to create your GUI. 45 | 46 | - Option 3 - Headless main modules package: ``pip install opencv-python-headless`` 47 | - Option 4 - Headless full package (contains both main modules and contrib/extra modules): ``pip install opencv-contrib-python-headless`` (check contrib/extra modules listing from [OpenCV documentation](https://docs.opencv.org/master/)) 48 | 49 | 4. Import the package: 50 | 51 | ``import cv2`` 52 | 53 | All packages contain Haar cascade files. ``cv2.data.haarcascades`` can be used as a shortcut to the data folder. For example: 54 | 55 | ``cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml")`` 56 | 57 | 5. Read [OpenCV documentation](https://docs.opencv.org/master/) 58 | 59 | 6. Before opening a new issue, read the FAQ below and have a look at the other issues which are already open. 60 | 61 | Frequently Asked Questions 62 | -------------------------- 63 | 64 | **Q: Do I need to install also OpenCV separately?** 65 | 66 | A: No, the packages are special wheel binary packages and they already contain statically built OpenCV binaries. 67 | 68 | **Q: Pip install fails with ``ModuleNotFoundError: No module named 'skbuild'``?** 69 | 70 | Since ``opencv-python`` version 4.3.0.\*, ``manylinux1`` wheels were replaced by ``manylinux2014`` wheels. If your pip is too old, it will try to use the new source distribution introduced in 4.3.0.38 to manually build OpenCV because it does not know how to install ``manylinux2014`` wheels. However, source build will also fail because of too old ``pip`` because it does not understand build dependencies in ``pyproject.toml``. To use the new ``manylinux2014`` pre-built wheels (or to build from source), your ``pip`` version must be >= 19.3. Please upgrade ``pip`` with ``pip install --upgrade pip``. 71 | 72 | **Q: Import fails on Windows: ``ImportError: DLL load failed: The specified module could not be found.``?** 73 | 74 | A: If the import fails on Windows, make sure you have [Visual C++ redistributable 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145) installed. If you are using older Windows version than Windows 10 and latest system updates are not installed, [Universal C Runtime](https://support.microsoft.com/en-us/help/2999226/update-for-universal-c-runtime-in-windows) might be also required. 75 | 76 | Windows N and KN editions do not include Media Feature Pack which is required by OpenCV. If you are using Windows N or KN edition, please install also [Windows Media Feature Pack](https://support.microsoft.com/en-us/help/3145500/media-feature-pack-list-for-windows-n-editions). 77 | 78 | If you have Windows Server 2012+, media DLLs are probably missing too; please install the Feature called "Media Foundation" in the Server Manager. Beware, some posts advise to install "Windows Server Essentials Media Pack", but this one requires the "Windows Server Essentials Experience" role, and this role will deeply affect your Windows Server configuration (by enforcing active directory integration etc.); so just installing the "Media Foundation" should be a safer choice. 79 | 80 | If the above does not help, check if you are using Anaconda. Old Anaconda versions have a bug which causes the error, see [this issue](https://github.com/opencv/opencv-python/issues/36) for a manual fix. 81 | 82 | If you still encounter the error after you have checked all the previous solutions, download [Dependencies](https://github.com/lucasg/Dependencies) and open the ``cv2.pyd`` (located usually at ``C:\Users\username\AppData\Local\Programs\Python\PythonXX\Lib\site-packages\cv2``) file with it to debug missing DLL issues. 83 | 84 | **Q: I have some other import errors?** 85 | 86 | A: Make sure you have removed old manual installations of OpenCV Python bindings (cv2.so or cv2.pyd in site-packages). 87 | 88 | **Q: Function foo() or method bar() returns wrong result, throws exception or crashes interpreter. What should I do?** 89 | 90 | A: The repository contains only OpenCV-Python package build scripts, but not OpenCV itself. Python bindings for OpenCV are developed in official OpenCV repository and it's the best place to report issues. Also please check [OpenCV wiki](https://github.com/opencv/opencv/wiki) and [the official OpenCV forum](https://forum.opencv.org/) before file new bugs. 91 | 92 | **Q: Why the packages do not include non-free algorithms?** 93 | 94 | A: Non-free algorithms such as SURF are not included in these packages because they are patented / non-free and therefore cannot be distributed as built binaries. Note that SIFT is included in the builds due to patent expiration since OpenCV versions 4.3.0 and 3.4.10. See this issue for more info: https://github.com/skvark/opencv-python/issues/126 95 | 96 | **Q: Why the package and import are different (opencv-python vs. cv2)?** 97 | 98 | A: It's easier for users to understand ``opencv-python`` than ``cv2`` and it makes it easier to find the package with search engines. `cv2` (old interface in old OpenCV versions was named as `cv`) is the name that OpenCV developers chose when they created the binding generators. This is kept as the import name to be consistent with different kind of tutorials around the internet. Changing the import name or behaviour would be also confusing to experienced users who are accustomed to the ``import cv2``. 99 | 100 | ## Documentation for opencv-python 101 | 102 | [![Windows Build Status](https://github.com/opencv/opencv-python/actions/workflows/build_wheels_windows.yml/badge.svg)](https://github.com/opencv/opencv-python/actions/workflows/build_wheels_windows.yml) 103 | [![(Linux Build status)](https://github.com/opencv/opencv-python/actions/workflows/build_wheels_linux.yml/badge.svg)](https://github.com/opencv/opencv-python/actions/workflows/build_wheels_linux.yml) 104 | [![(Mac OS Build status)](https://github.com/opencv/opencv-python/actions/workflows/build_wheels_macos.yml/badge.svg)](https://github.com/opencv/opencv-python/actions/workflows/build_wheels_macos.yml) 105 | 106 | The aim of this repository is to provide means to package each new [OpenCV release](https://github.com/opencv/opencv/releases) for the most used Python versions and platforms. 107 | 108 | ### CI build process 109 | 110 | The project is structured like a normal Python package with a standard ``setup.py`` file. 111 | The build process for a single entry in the build matrices is as follows (see for example `.github/workflows/build_wheels_linux.yml` file): 112 | 113 | 0. In Linux and MacOS build: get OpenCV's optional C dependencies that we compile against 114 | 115 | 1. Checkout repository and submodules 116 | 117 | - OpenCV is included as submodule and the version is updated 118 | manually by maintainers when a new OpenCV release has been made 119 | - Contrib modules are also included as a submodule 120 | 121 | 2. Find OpenCV version from the sources 122 | 123 | 3. Build OpenCV 124 | 125 | - tests are disabled, otherwise build time increases too much 126 | - there are 4 build matrix entries for each build combination: with and without contrib modules, with and without GUI (headless) 127 | - Linux builds run in manylinux Docker containers (CentOS 5) 128 | - source distributions are separate entries in the build matrix 129 | 130 | 4. Rearrange OpenCV's build result, add our custom files and generate wheel 131 | 132 | 5. Linux and macOS wheels are transformed with auditwheel and delocate, correspondingly 133 | 134 | 6. Install the generated wheel 135 | 7. Test that Python can import the library and run some sanity checks 136 | 8. Use twine to upload the generated wheel to PyPI (only in release builds) 137 | 138 | Steps 1--4 are handled by ``pip wheel``. 139 | 140 | The build can be customized with environment variables. In addition to any variables that OpenCV's build accepts, we recognize: 141 | 142 | - ``CI_BUILD``. Set to ``1`` to emulate the CI environment build behaviour. Used only in CI builds to force certain build flags on in ``setup.py``. Do not use this unless you know what you are doing. 143 | - ``ENABLE_CONTRIB`` and ``ENABLE_HEADLESS``. Set to ``1`` to build the contrib and/or headless version 144 | - ``ENABLE_JAVA``, Set to ``1`` to enable the Java client build. This is disabled by default. 145 | - ``CMAKE_ARGS``. Additional arguments for OpenCV's CMake invocation. You can use this to make a custom build. 146 | 147 | See the next section for more info about manual builds outside the CI environment. 148 | 149 | ### Manual builds 150 | 151 | If some dependency is not enabled in the pre-built wheels, you can also run the build locally to create a custom wheel. 152 | 153 | 1. Clone this repository: `git clone --recursive https://github.com/opencv/opencv-python.git` 154 | 2. ``cd opencv-python`` 155 | - you can use `git` to checkout some other version of OpenCV in the `opencv` and `opencv_contrib` submodules if needed 156 | 3. Add custom Cmake flags if needed, for example: `export CMAKE_ARGS="-DSOME_FLAG=ON -DSOME_OTHER_FLAG=OFF"` (in Windows you need to set environment variables differently depending on Command Line or PowerShell) 157 | 4. Select the package flavor which you wish to build with `ENABLE_CONTRIB` and `ENABLE_HEADLESS`: i.e. `export ENABLE_CONTRIB=1` if you wish to build `opencv-contrib-python` 158 | 5. Run ``pip wheel . --verbose``. NOTE: make sure you have the latest ``pip`` version, the ``pip wheel`` command replaces the old ``python setup.py bdist_wheel`` command which does not support ``pyproject.toml``. 159 | - this might take anything from 5 minutes to over 2 hours depending on your hardware 160 | 6. Pip will print fresh wheel location at the end of build procedure. If you use old approach with `setup.py` file wheel package will be placed in `dist` folder. Package is ready and you can do with that whatever you wish. 161 | - Optional: on Linux use some of the `manylinux` images as a build hosts if maximum portability is needed and run `auditwheel` for the wheel after build 162 | - Optional: on macOS use ``delocate`` (same as ``auditwheel`` but for macOS) for better portability 163 | 164 | #### Manual debug builds 165 | 166 | In order to build `opencv-python` in an unoptimized debug build, you need to side-step the normal process a bit. 167 | 168 | 1. Install the packages `scikit-build` and `numpy` via pip. 169 | 2. Run the command `python setup.py bdist_wheel --build-type=Debug`. 170 | 3. Install the generated wheel file in the `dist/` folder with `pip install dist/wheelname.whl`. 171 | 172 | If you would like the build produce all compiler commands, then the following combination of flags and environment variables has been tested to work on Linux: 173 | ``` 174 | export CMAKE_ARGS='-DCMAKE_VERBOSE_MAKEFILE=ON' 175 | export VERBOSE=1 176 | 177 | python3 setup.py bdist_wheel --build-type=Debug 178 | ``` 179 | 180 | See this issue for more discussion: https://github.com/opencv/opencv-python/issues/424 181 | 182 | #### Source distributions 183 | 184 | Since OpenCV version 4.3.0, also source distributions are provided in PyPI. This means that if your system is not compatible with any of the wheels in PyPI, ``pip`` will attempt to build OpenCV from sources. If you need a OpenCV version which is not available in PyPI as a source distribution, please follow the manual build guidance above instead of this one. 185 | 186 | You can also force ``pip`` to build the wheels from the source distribution. Some examples: 187 | 188 | - ``pip install --no-binary opencv-python opencv-python`` 189 | - ``pip install --no-binary :all: opencv-python`` 190 | 191 | If you need contrib modules or headless version, just change the package name (step 4 in the previous section is not needed). However, any additional CMake flags can be provided via environment variables as described in step 3 of the manual build section. If none are provided, OpenCV's CMake scripts will attempt to find and enable any suitable dependencies. Headless distributions have hard coded CMake flags which disable all possible GUI dependencies. 192 | 193 | On slow systems such as Raspberry Pi the full build may take several hours. On a 8-core Ryzen 7 3700X the build takes about 6 minutes. 194 | 195 | ### Licensing 196 | 197 | Opencv-python package (scripts in this repository) is available under MIT license. 198 | 199 | OpenCV itself is available under [Apache 2](https://github.com/opencv/opencv/blob/master/LICENSE) license. 200 | 201 | Third party package licenses are at [LICENSE-3RD-PARTY.txt](https://github.com/opencv/opencv-python/blob/master/LICENSE-3RD-PARTY.txt). 202 | 203 | All wheels ship with [FFmpeg](http://ffmpeg.org) licensed under the [LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html). 204 | 205 | Non-headless Linux wheels ship with [Qt 5](http://doc.qt.io/qt-5/lgpl.html) licensed under the [LGPLv3](http://www.gnu.org/licenses/lgpl-3.0.html). 206 | 207 | The packages include also other binaries. Full list of licenses can be found from [LICENSE-3RD-PARTY.txt](https://github.com/opencv/opencv-python/blob/master/LICENSE-3RD-PARTY.txt). 208 | 209 | ### Versioning 210 | 211 | ``find_version.py`` script searches for the version information from OpenCV sources and appends also a revision number specific to this repository to the version string. It saves the version information to ``version.py`` file under ``cv2`` in addition to some other flags. 212 | 213 | ### Releases 214 | 215 | A release is made and uploaded to PyPI when a new tag is pushed to master branch. These tags differentiate packages (this repo might have modifications but OpenCV version stays same) and should be incremented sequentially. In practice, release version numbers look like this: 216 | 217 | ``cv_major.cv_minor.cv_revision.package_revision`` e.g. ``3.1.0.0`` 218 | 219 | The master branch follows OpenCV master branch releases. 3.4 branch follows OpenCV 3.4 bugfix releases. 220 | 221 | ### Development builds 222 | 223 | Every commit to the master branch of this repo will be built. Possible build artifacts use local version identifiers: 224 | 225 | ``cv_major.cv_minor.cv_revision+git_hash_of_this_repo`` e.g. ``3.1.0+14a8d39`` 226 | 227 | These artifacts can't be and will not be uploaded to PyPI. 228 | 229 | ### Manylinux wheels 230 | 231 | Linux wheels are built using [manylinux2014](https://github.com/pypa/manylinux). These wheels should work out of the box for most of the distros (which use GNU C standard library) out there since they are built against an old version of glibc. 232 | 233 | The default ``manylinux2014`` images have been extended with some OpenCV dependencies. See [Docker folder](https://github.com/skvark/opencv-python/tree/master/docker) for more info. 234 | 235 | ### Supported Python versions 236 | 237 | Python 3.x compatible pre-built wheels are provided for the officially supported Python versions (not in EOL): 238 | 239 | - 3.7 240 | - 3.8 241 | - 3.9 242 | - 3.10 243 | - 3.11 244 | - 3.12 245 | - 3.13 246 | 247 | ### Backward compatibility 248 | 249 | Starting from 4.2.0 and 3.4.9 builds the macOS Travis build environment was updated to XCode 9.4. The change effectively dropped support for older than 10.13 macOS versions. 250 | 251 | Starting from 4.3.0 and 3.4.10 builds the Linux build environment was updated from `manylinux1` to `manylinux2014`. This dropped support for old Linux distributions. 252 | 253 | Starting from version 4.7.0 the Mac OS GitHub Actions build environment was update to version 11. Mac OS 10.x support deprecated. See https://github.com/actions/runner-images/issues/5583 254 | 255 | Starting from version 4.9.0 the Mac OS GitHub Actions build environment was update to version 12. Mac OS 10.x support deprecated by Brew and most of used packages. 256 | -------------------------------------------------------------------------------- /travis_osx_brew_cache.sh: -------------------------------------------------------------------------------- 1 | # Library to cache downloaded and locally-built Homebrew bottles in Travis OSX build. 2 | 3 | 4 | #Should be in Travis' cache 5 | BREW_LOCAL_BOTTLE_METADATA="$HOME/local_bottle_metadata" 6 | 7 | #FIXME: temporary fix to enable the build, should be replaced with the proper path to the cache dir 8 | mkdir -p $BREW_LOCAL_BOTTLE_METADATA 9 | 10 | # Starting reference point for elapsed build time; seconds since the epoch. 11 | #TRAVIS_TIMER_START_TIME is set at the start of a log fold, in nanoseconds since the epoch 12 | BREW_TIME_START=$(($TRAVIS_TIMER_START_TIME/10**9)) 13 | 14 | # If after a package is built, elapsed time is more than this many seconds, fail the build but save Travis cache 15 | # The cutoff moment should leave enough time till Travis' job time limit to process the main project. 16 | # Since we have moved deps into a separate stage, we don't need to leave time for the project any more 17 | BREW_TIME_LIMIT=$((42*60)) 18 | # If a slow-building package is about to be built and the projected build end moment is beyond this many seconds, 19 | # skip that build, fail the Travis job and save Travis cache. 20 | # This cutoff should leave enough time for before_cache and cache save. 21 | BREW_TIME_HARD_LIMIT=$((43*60)) 22 | 23 | 24 | # Auto cleanup can delete locally-built bottles 25 | # when the caching logic isn't prepared for that 26 | export HOMEBREW_NO_INSTALL_CLEANUP=1 27 | 28 | # Don't query analytical info online on `brew info`, 29 | # this takes several seconds and we don't need it 30 | # see https://docs.brew.sh/Manpage , "info formula" section 31 | export HOMEBREW_NO_GITHUB_API=1 32 | 33 | #Packages already installed in the current session to avoid checking them again 34 | _BREW_ALREADY_INSTALLED='$' #$ = illegal package name; a blank line would cause macos grep to swallow everything 35 | 36 | 37 | #Public functions 38 | 39 | function brew_install_and_cache_within_time_limit { 40 | # Install the package and its dependencies one by one; 41 | # use bottle if available, build and cache bottle if not. 42 | # Terminate and exit with status 1 if this takes too long. 43 | # Exit with status 2 on any other error. 44 | _brew_install_and_cache_within_time_limit $@ \ 45 | || if test $? -eq 1; then brew_go_bootstrap_mode; return 1; else return 2; fi 46 | } 47 | 48 | function brew_add_local_bottles { 49 | # Should be called after `brew update` at startup. 50 | # Adds metadata for cached locally-built bottles to local formulas 51 | # so that `brew` commands can find them. 52 | # If the package was updated, removes the corresponding files 53 | # and the bottle's entry in the formula, if any. 54 | 55 | # Bottle entry in formula: 56 | # bottle do 57 | # <...> 58 | # sha256 "" => : 59 | # <...> 60 | # end 61 | 62 | echo "Cached bottles:" 63 | ls "$(brew --cache)/downloads" || true #may not exist initially since it's "$(brew --cache)" that is in Travis cache 64 | echo "Saved .json's and links:" 65 | ls "$BREW_LOCAL_BOTTLE_METADATA" 66 | 67 | for JSON in "$BREW_LOCAL_BOTTLE_METADATA"/*.json; do 68 | [ -e "$JSON" ] || break # OSX 10.11 bash has no nullglob 69 | local PACKAGE JSON_VERSION JSON_REBUILD OS_CODENAME BOTTLE_HASH 70 | 71 | _brew_parse_bottle_json "$JSON" PACKAGE JSON_VERSION JSON_REBUILD OS_CODENAME BOTTLE_HASH 72 | 73 | echo "Adding local bottle: $PACKAGE ${JSON_VERSION}_${JSON_REBUILD}" 74 | 75 | local FORMULA_VERSION FORMULA_REBUILD FORMULA_BOTTLE_HASH 76 | 77 | _brew_parse_package_info "$PACKAGE" "$OS_CODENAME" FORMULA_VERSION FORMULA_REBUILD FORMULA_BOTTLE_HASH 78 | 79 | local FORMULA_HAS_BOTTLE; [ -n "$FORMULA_BOTTLE_HASH" ] && FORMULA_HAS_BOTTLE=1 || true 80 | 81 | 82 | local BOTTLE_LINK BOTTLE=""; BOTTLE_LINK="${JSON}.bottle.lnk"; 83 | local BOTTLE_EXISTS= BOTTLE_MISMATCH= VERSION_MISMATCH= 84 | 85 | 86 | # Check that the bottle file exists and is still appropriate for the formula 87 | if [[ "$FORMULA_VERSION" != "$JSON_VERSION" || "$JSON_REBUILD" != "$FORMULA_REBUILD" ]]; then 88 | VERSION_MISMATCH=1; 89 | echo "The cached bottle is obsolete: formula ${FORMULA_VERSION}_${FORMULA_REBUILD}" 90 | fi 91 | if [ -f "$BOTTLE_LINK" ]; then 92 | BOTTLE=$(cat "$BOTTLE_LINK"); 93 | BOTTLE=$(cd "$(dirname "$BOTTLE")"; pwd)/$(basename "$BOTTLE") 94 | 95 | if [ -e "$BOTTLE" ]; then 96 | BOTTLE_EXISTS=1; 97 | 98 | # The hash in `brew --cache $PACKAGE` entry is generated from download URL, 99 | # which itself is generated from base URL and version 100 | # (see Homebrew/Library/Homebrew/download_strategy.rb:cached_location). 101 | # So if version changes, hashes will always mismatch anyway 102 | # and we don't need a separate message about this. 103 | # XXX: OSX doesn't have `realpath` so can't compare the entire paths 104 | if [ -n "$FORMULA_HAS_BOTTLE" -a -z "$VERSION_MISMATCH" -a \ 105 | "$(basename "$(brew --cache "$PACKAGE")")" != "$(basename "$BOTTLE")" ]; then 106 | BOTTLE_MISMATCH=1; 107 | echo "Cached bottle file doesn't correspond to formula's cache entry!" \ 108 | "This can happen if download URL has changed." >&2 109 | fi 110 | else 111 | echo "Cached bottle file is missing!" >&2 112 | fi 113 | else 114 | echo "Link file is missing or of invalid type!" >&2 115 | fi 116 | 117 | # Delete cached bottle and all metadata if invalid 118 | if [[ -z "$BOTTLE_EXISTS" || -n "$VERSION_MISMATCH" || -n "$BOTTLE_MISMATCH" ]]; then 119 | echo "Deleting the cached bottle and all metadata" 120 | 121 | if [ "$FORMULA_BOTTLE_HASH" == "$BOTTLE_HASH" ]; then 122 | echo "A bottle block for the cached bottle was merged into the updated formula. Removing..." 123 | local FORMULA; FORMULA=$(brew formula "$PACKAGE") 124 | perl -wpe 'BEGIN { our $IN_BLOCK=0; } 125 | if ( ($IN_BLOCK==0) && /^\s*bottle\s+do\s*$/ ) { $IN_BLOCK=1; next; } 126 | if ( ($IN_BLOCK==1) && /^\s*end\s*$/ ) { $IN_BLOCK=-1; next; } 127 | if ( ($IN_BLOCK==1) && /^\s*sha256\s+"(\w+)"\s+=>\s+:\w+\s*$/ ) 128 | { if ( $1 eq "'"$BOTTLE_HASH"'" ) {$_="";}; next; } 129 | ' <"$FORMULA" >"${FORMULA}.new" 130 | # Depending on diff version, 1 may mean differences found 131 | # https://stackoverflow.com/questions/6971284/what-are-the-error-exit-values-for-diff 132 | diff -u "$FORMULA" "${FORMULA}.new" || test $? -le 1 133 | ( cd $(dirname "$FORMULA") 134 | FORMULA=$(basename "$FORMULA") 135 | mv -v "${FORMULA}.new" "$FORMULA" 136 | git commit -m "Removed obsolete local bottle ${JSON_VERSION}_${JSON_REBUILD} :${OS_CODENAME}" "$FORMULA" 137 | ) 138 | fi 139 | 140 | if [ -n "$BOTTLE" -a -n "$BOTTLE_EXISTS" ]; then rm "$BOTTLE"; fi 141 | rm -f "$BOTTLE_LINK" 142 | rm "$JSON" 143 | 144 | #(Re)add metadata to the formula otherwise 145 | else 146 | if [ "$FORMULA_BOTTLE_HASH" == "$BOTTLE_HASH" ]; then 147 | echo "The cached bottle is already present in the formula" 148 | else 149 | brew bottle --merge --write "$JSON" 150 | fi 151 | fi 152 | done 153 | } 154 | 155 | 156 | function brew_cache_cleanup { 157 | #Cleanup caching directories 158 | # Is supposed to be called in before_cache 159 | 160 | #Lefovers from some failure probably 161 | rm -f "$BREW_LOCAL_BOTTLE_METADATA"/*.tar.gz 162 | 163 | #`brew cleanup` may delete locally-built bottles that weren't needed this time 164 | # so we're saving and restoring them 165 | local BOTTLE_LINK BOTTLE 166 | for BOTTLE_LINK in "$BREW_LOCAL_BOTTLE_METADATA"/*.lnk; do 167 | [ -e "$BOTTLE_LINK" ] || break 168 | BOTTLE=$(cat "$BOTTLE_LINK") 169 | ln "$BOTTLE" "$BREW_LOCAL_BOTTLE_METADATA/" 170 | done 171 | brew cleanup 172 | local BOTTLE_BASENAME 173 | for BOTTLE_LINK in "$BREW_LOCAL_BOTTLE_METADATA"/*.lnk; do 174 | [ -e "$BOTTLE_LINK" ] || break 175 | BOTTLE=$(cat "$BOTTLE_LINK") 176 | BOTTLE_BASENAME=$(basename "$BOTTLE") 177 | if test ! -e "$BOTTLE"; then 178 | echo "Restoring: $BOTTLE_BASENAME" 179 | mv "$BREW_LOCAL_BOTTLE_METADATA/$BOTTLE_BASENAME" "$BOTTLE" 180 | else 181 | rm "$BREW_LOCAL_BOTTLE_METADATA/$BOTTLE_BASENAME" 182 | fi 183 | done 184 | } 185 | 186 | 187 | function brew_go_bootstrap_mode { 188 | # Can be overridden 189 | # Terminate the build but ensure saving the cache 190 | local EXIT_CODE=${1:-1} 191 | 192 | echo "Going into cache bootstrap mode" 193 | 194 | BREW_BOOTSTRAP_MODE=1 195 | 196 | #Can't just `exit` because that would terminate the build without saving the cache 197 | #Have to replace further actions with no-ops 198 | 199 | local MESSAGE=""; if [ "$EXIT_CODE" -ne 0 ]; then 200 | MESSAGE='Building dependencies took too long. Restart the build in Travis UI to continue from cache.'; 201 | fi 202 | 203 | eval ' 204 | function '"$cmd"' { return 0; } 205 | function repair_wheelhouse { return 0; } 206 | function install_run {'\ 207 | "$(if [ -n "$MESSAGE" ]; then 208 | echo \ 209 | ' echo -e "\n'"$MESSAGE"'\n"' 210 | fi)"\ 211 | ' 212 | # Travis runs user scripts via `eval` i.e. in the same shell process. 213 | # So have to unset errexit in order to get to cache save stage 214 | set +e; return '"$EXIT_CODE"' 215 | }' 216 | } 217 | 218 | 219 | 220 | #Internal functions 221 | 222 | function _brew_install_and_cache_within_time_limit { 223 | # This fn is run with || so errexit can't be enabled 224 | 225 | local PACKAGE TIME_LIMIT TIME_HARD_LIMIT TIME_START MARKED_INSTALLED 226 | PACKAGE="${1:?}" || return 2 227 | TIME_LIMIT=${2:-$BREW_TIME_LIMIT} || return 2 228 | TIME_HARD_LIMIT=${3:-$BREW_TIME_HARD_LIMIT} || return 2 229 | TIME_START=${4:-$BREW_TIME_START} || return 2 230 | 231 | if grep -qxFf <(cat <<<"$_BREW_ALREADY_INSTALLED") <<<"$PACKAGE"; then 232 | MARKED_INSTALLED=1 233 | fi 234 | 235 | if [ -n "$MARKED_INSTALLED" ] || (brew list --versions "$PACKAGE" >/dev/null && ! (brew outdated | grep -qxF "$PACKAGE")); then 236 | echo "Already installed and the latest version: $PACKAGE" 237 | if [ -z "$MARKED_INSTALLED" ]; then _brew_mark_installed "$PACKAGE"; fi 238 | return 0 239 | fi 240 | 241 | local BUILD_FROM_SOURCE INCLUDE_BUILD KEG_ONLY 242 | 243 | _brew_is_bottle_available "$PACKAGE" KEG_ONLY || BUILD_FROM_SOURCE=1 244 | [ -n "$BUILD_FROM_SOURCE" ] && INCLUDE_BUILD="--include-build" || true 245 | 246 | # Whitespace is illegal in package names so converting all whitespace into single spaces due to no quotes is okay. 247 | DEPS=`brew deps "$PACKAGE" $INCLUDE_BUILD` || return 2 248 | DEPS=`grep -vxF <(cat <<<"$_BREW_ALREADY_INSTALLED") <<<"$DEPS"` || test $? -eq 1 || return 2 249 | for dep in $DEPS; do 250 | #TIME_LIMIT only has to be met if we'll be actually building the main project this iteration, i.e. after the "root" module installation 251 | #While we don't know that yet, we can make better use of Travis-given time with a laxer limit 252 | #We still can't overrun TIME_HARD_LIMIT as that wouldn't leave time to save the cache 253 | _brew_install_and_cache_within_time_limit "$dep" $(((TIME_LIMIT+TIME_HARD_LIMIT)/2)) "$TIME_HARD_LIMIT" "$TIME_START" || return $? 254 | done 255 | 256 | _brew_check_slow_building_ahead "$PACKAGE" "$TIME_START" "$TIME_HARD_LIMIT" || return $? 257 | _brew_install_and_cache "$PACKAGE" "$([[ -z "$BUILD_FROM_SOURCE" ]] && echo 1 || echo 0)" "$KEG_ONLY" || return 2 258 | _brew_check_elapsed_build_time "$TIME_START" "$TIME_LIMIT" || return $? 259 | } 260 | 261 | 262 | function _brew_parse_bottle_json { 263 | # Parse JSON file resulting from `brew bottle --json` 264 | # and save data into specified variables 265 | 266 | local JSON; JSON="${1:?}"; shift 267 | 268 | local JSON_DATA; JSON_DATA=$(python3 -c 'if True: 269 | import sys,json; j=json.load(open(sys.argv[1],"rb")); [name]=j.keys(); [pdata]=j.values() 270 | print(name) 271 | print(pdata["formula"]["pkg_version"]) 272 | print(pdata["bottle"]["rebuild"]) 273 | [(tag_name, tag_dict)]=pdata["bottle"]["tags"].items() 274 | print(tag_name) 275 | print(tag_dict["sha256"]) 276 | ' "$JSON") 277 | 278 | unset JSON 279 | 280 | { local i v; for i in {1..5}; do 281 | read -r v 282 | eval "${1:?}=\"$v\"" 283 | shift 284 | done } <<< "$JSON_DATA" 285 | } 286 | 287 | function _brew_parse_package_info { 288 | # Get and parse `brew info --json` about a package 289 | # and save data into specified variables 290 | 291 | local PACKAGE OS_CODENAME 292 | PACKAGE="${1:?}"; shift 293 | OS_CODENAME="${1:?}"; shift 294 | 295 | local JSON_DATA; JSON_DATA=$(python3 -c 'if True: 296 | import sys, json, subprocess; j=json.loads(subprocess.check_output(("brew","info","--json=v1",sys.argv[1]))) 297 | data=j[0] 298 | revision=data["revision"] 299 | # in bottle''s json, revision is included into version; here, they are separate 300 | print(data["versions"]["stable"]+("_"+str(revision) if revision else "")) 301 | bottle_data=data["bottle"].get("stable",{"rebuild":"","files":{}}) 302 | print(bottle_data["rebuild"]) 303 | print(bottle_data["files"].get(sys.argv[2],{"sha256":"!?"})["sha256"]) #prevent losing trailing blank line to command substitution 304 | ' \ 305 | "$PACKAGE" "$OS_CODENAME"); JSON_DATA="${JSON_DATA%\!\?}" #!? can't occur in a hash 306 | 307 | unset PACKAGE OS_CODENAME 308 | 309 | { local i v; for i in {1..3}; do 310 | read -r v 311 | eval "${1:?}=\"$v\"" 312 | shift 313 | done } <<< "$JSON_DATA" 314 | } 315 | 316 | 317 | 318 | function _brew_is_bottle_available { 319 | 320 | local PACKAGE;PACKAGE="${1:?}" 321 | local VAR_KEG_ONLY="$2" 322 | 323 | # `brew info` prints "Error: Broken pipe" if piped directly to `head` and the info is long 324 | # 141 = 128 + SIGPIPE 325 | local INFO;INFO="$((brew info "$PACKAGE" | cat || test $? -eq 141) | head -n 1)" 326 | if [ -n "$VAR_KEG_ONLY" ]; then 327 | if grep -qwF '[keg-only]' <<<"$INFO"; then 328 | eval "${VAR_KEG_ONLY}=1" 329 | else 330 | eval "${VAR_KEG_ONLY}=0" 331 | fi 332 | fi 333 | 334 | if grep -qxEe '[[:space:]]*bottle :unneeded' $(brew formula "$PACKAGE"); then 335 | echo "Bottle disabled: $PACKAGE" 336 | return 0 337 | fi 338 | 339 | if grep -qwF '(bottled)' <<<"$INFO"; then 340 | echo "Bottle available: $INFO" 341 | return 0 342 | else 343 | echo "Bottle not available: $INFO" 344 | return 1 345 | fi 346 | } 347 | 348 | function _brew_install_and_cache { 349 | # Install bottle or make and cache bottle. 350 | # assumes that deps were already installed 351 | # and not already the latest version 352 | 353 | local PACKAGE USE_BOTTLE KEG_ONLY 354 | PACKAGE="${1:?}" 355 | USE_BOTTLE="${2:?}" 356 | KEG_ONLY="${3:?}" 357 | local VERB 358 | 359 | if brew list --versions "$PACKAGE"; then 360 | # Install alongside the old version to avoid to have to update "runtime dependents" 361 | # https://discourse.brew.sh/t/can-i-install-a-new-version-without-having-to-upgrade-runtime-dependents/4443 362 | VERB="install --force" 363 | if [ "$KEG_ONLY" -eq 0 ]; then 364 | brew unlink "$PACKAGE" 365 | fi 366 | else 367 | VERB=install 368 | fi 369 | 370 | if [[ "$USE_BOTTLE" -gt 0 ]]; then 371 | echo "Installing bottle for: $PACKAGE" 372 | brew $VERB "$PACKAGE" 373 | else 374 | echo "Building bottle for: $PACKAGE" 375 | brew $VERB --build-bottle "$PACKAGE" 376 | exec 3>&1 377 | local OUT=$(brew bottle --json "$PACKAGE" | tee /dev/fd/3) 378 | exec 3>&- 379 | 380 | ls "$PACKAGE"* 381 | # doesn't seem to be a documented way to get file names 382 | local BOTTLE; BOTTLE=$(grep -Ee '^./' <<<"$OUT") 383 | #proper procedure as per https://discourse.brew.sh/t/how-are-bottle-and-postinstall-related-is-it-safe-to-run-bottle-after-postinstall/3410/4 384 | brew uninstall --ignore-dependencies "$PACKAGE" 385 | brew $VERB "$BOTTLE" 386 | 387 | local JSON; JSON=$(sed -E 's/bottle(.[[:digit:]]+)?\.tar\.gz$/bottle.json/' <<<"$BOTTLE") 388 | 389 | #`brew bottle --merge` doesn't return nonzero on nonexisting json file 390 | test -f "$JSON" -a -f "$BOTTLE" 391 | 392 | brew bottle --merge --write "$JSON" 393 | local CACHED_BOTTLE; CACHED_BOTTLE="$(brew --cache "$PACKAGE")" 394 | mv "$BOTTLE" "$CACHED_BOTTLE"; 395 | local CACHED_JSON; CACHED_JSON="${BREW_LOCAL_BOTTLE_METADATA}/$(basename "$JSON")" 396 | mv "$JSON" "$CACHED_JSON" 397 | #Symlinks aren't cached by Travis. Will just save paths in files then. 398 | local BOTTLE_LINK; BOTTLE_LINK="${CACHED_JSON}.bottle.lnk" 399 | echo "$CACHED_BOTTLE" >"$BOTTLE_LINK" 400 | 401 | fi 402 | 403 | _brew_mark_installed "$PACKAGE" 404 | } 405 | 406 | function _brew_mark_installed { 407 | _BREW_ALREADY_INSTALLED="$_BREW_ALREADY_INSTALLED"$'\n'"${1:?}" 408 | } 409 | 410 | function _brew_check_elapsed_build_time { 411 | # If time limit has been reached, 412 | # arrange for further build to be skipped and return 1 413 | 414 | local TIME_START TIME_LIMIT ELAPSED_TIME 415 | TIME_START="${1:?}" 416 | TIME_LIMIT="${2:?}" 417 | 418 | ELAPSED_TIME=$(($(date +%s) - $TIME_START)) 419 | echo "Elapsed time: "$(($ELAPSED_TIME/60))"m (${ELAPSED_TIME}s)" 420 | 421 | if [[ "$ELAPSED_TIME" -gt $TIME_LIMIT ]]; then 422 | brew_go_bootstrap_mode 423 | return 1 424 | fi 425 | return 0 426 | } 427 | 428 | function _brew_check_slow_building_ahead { 429 | 430 | #If the package's projected build completion is higher than hard limit, 431 | # skip it and arrange for further build to be skipped and return 1 432 | 433 | local PACKAGE TIME_START TIME_HARD_LIMIT 434 | PACKAGE="${1:?}" 435 | TIME_START="${2:?}" 436 | TIME_HARD_LIMIT="${3:?}" 437 | 438 | local PROJECTED_BUILD_TIME 439 | PROJECTED_BUILD_TIME=$(echo "$BREW_SLOW_BUILIDING_PACKAGES" | awk '$1=="'"$PACKAGE"'"{print $2}') 440 | [ -z "$PROJECTED_BUILD_TIME" ] && return 0 || true 441 | 442 | local PROJECTED_BUILD_END_ELAPSED_TIME 443 | PROJECTED_BUILD_END_ELAPSED_TIME=$(( $(date +%s) - TIME_START + PROJECTED_BUILD_TIME * 60)) 444 | 445 | if [[ "$PROJECTED_BUILD_END_ELAPSED_TIME" -ge "$TIME_HARD_LIMIT" ]]; then 446 | echo -e "\nProjected build end elapsed time for $PACKAGE: $((PROJECTED_BUILD_END_ELAPSED_TIME/60))m ($PROJECTED_BUILD_END_ELAPSED_TIMEs)" 447 | brew_go_bootstrap_mode 448 | return 1 449 | fi 450 | return 0 451 | } 452 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import io 2 | import os 3 | import os.path 4 | import sys 5 | import runpy 6 | import subprocess 7 | import re 8 | import sysconfig 9 | import platform 10 | from skbuild import cmaker, setup 11 | 12 | 13 | def main(): 14 | os.chdir(os.path.dirname(os.path.abspath(__file__))) 15 | 16 | CI_BUILD = os.environ.get("CI_BUILD", "False") 17 | is_CI_build = True if CI_BUILD == "1" else False 18 | cmake_source_dir = "opencv" 19 | minimum_supported_numpy = "1.13.3" 20 | build_contrib = get_build_env_var_by_name("contrib") 21 | build_headless = get_build_env_var_by_name("headless") 22 | build_java = "ON" if get_build_env_var_by_name("java") else "OFF" 23 | build_rolling = get_build_env_var_by_name("rolling") 24 | 25 | install_requires = [ 26 | 'numpy<2.0; python_version<"3.9"', 27 | 'numpy>=2; python_version>="3.9"', 28 | ] 29 | 30 | python_version = cmaker.CMaker.get_python_version() 31 | python_lib_path = cmaker.CMaker.get_python_library(python_version) or "" 32 | # HACK: For Scikit-build 0.17.3 and newer that returns None or empty sptring for PYTHON_LIBRARY in manylinux2014 33 | # A small release related to PYTHON_LIBRARY handling changes in 0.17.2; scikit-build 0.17.3 returns an empty string from get_python_library if no Python library is present (like on manylinux), where 0.17.2 returned None, and previous versions returned a non-existent path. Note that adding REQUIRED to find_package(PythonLibs will fail, but it is incorrect (you must not link to libPython.so) and was really just injecting a non-existent path before. 34 | # TODO: Remove the hack when the issue is handled correctly in main OpenCV CMake. 35 | if python_lib_path == "": 36 | python_lib_path = "libpython%sm.a" % python_version 37 | python_lib_path = python_lib_path.replace("\\", "/") 38 | 39 | python_include_dir = cmaker.CMaker.get_python_include_dir(python_version).replace( 40 | "\\", "/" 41 | ) 42 | 43 | if not bool(os.environ.get('OPENCV_PYTHON_SKIP_GIT_COMMANDS', False)) and os.path.exists(".git"): 44 | import pip._internal.vcs.git as git 45 | 46 | g = git.Git() # NOTE: pip API's are internal, this has to be refactored 47 | 48 | g.run_command(["submodule", "sync"]) 49 | 50 | if build_rolling: 51 | g.run_command( 52 | ["submodule", "update", "--init", "--recursive", "--remote", cmake_source_dir] 53 | ) 54 | 55 | if build_contrib: 56 | g.run_command( 57 | ["submodule", "update", "--init", "--recursive", "--remote", "opencv_contrib"] 58 | ) 59 | else: 60 | g.run_command( 61 | ["submodule", "update", "--init", "--recursive", cmake_source_dir] 62 | ) 63 | 64 | if build_contrib: 65 | g.run_command( 66 | ["submodule", "update", "--init", "--recursive", "opencv_contrib"] 67 | ) 68 | 69 | package_version, build_contrib, build_headless, build_rolling = get_and_set_info( 70 | build_contrib, build_headless, build_rolling, is_CI_build 71 | ) 72 | 73 | # https://stackoverflow.com/questions/1405913/python-32bit-or-64bit-mode 74 | is64 = sys.maxsize > 2 ** 32 75 | 76 | package_name = "opencv-python" 77 | 78 | if build_contrib and not build_headless: 79 | package_name = "opencv-contrib-python" 80 | 81 | if build_contrib and build_headless: 82 | package_name = "opencv-contrib-python-headless" 83 | 84 | if build_headless and not build_contrib: 85 | package_name = "opencv-python-headless" 86 | 87 | if build_rolling: 88 | package_name += "-rolling" 89 | 90 | package_name = os.environ.get('OPENCV_PYTHON_PACKAGE_NAME', package_name) 91 | 92 | long_description = io.open("README.md", encoding="utf-8").read() 93 | 94 | packages = ["cv2", "cv2.data"] 95 | 96 | package_data = { 97 | "cv2": ["*%s" % sysconfig.get_config_vars().get("SO"), "version.py"] 98 | + (["*.dll"] if os.name == "nt" else []) 99 | + ["LICENSE.txt", "LICENSE-3RD-PARTY.txt"], 100 | "cv2.data": ["*.xml"], 101 | } 102 | 103 | # Files from CMake output to copy to package. 104 | # Path regexes with forward slashes relative to CMake install dir. 105 | rearrange_cmake_output_data = { 106 | "cv2": ( 107 | [r"bin/opencv_videoio_ffmpeg\d{4}%s\.dll" % ("_64" if is64 else "")] 108 | if os.name == "nt" 109 | else [] 110 | ) 111 | + 112 | # In Windows, in python/X.Y//; in Linux, in just python/X.Y/. 113 | # Naming conventions vary so widely between versions and OSes 114 | # had to give up on checking them. 115 | # If not specifying PY_LIMITED_API, the Python sources go under python/cv2/python-3.MINOR_VERSION/ instead of python/cv2/python-3/ 116 | [ 117 | r"python/cv2/python-%s*/cv2.*" 118 | % (sys.version_info[0]) if 'CMAKE_ARGS' in os.environ and "-DPYTHON3_LIMITED_API=ON" in os.environ['CMAKE_ARGS'] 119 | else r"python/cv2/python-%s.*/cv2.*" 120 | % (sys.version_info[0]) 121 | ] 122 | + 123 | [ 124 | r"python/cv2/__init__.py" 125 | ] 126 | + 127 | [ 128 | r"python/cv2/.*config.*.py" 129 | ] 130 | + 131 | [ r"python/cv2/py.typed" ] if sys.version_info >= (3, 6) else [] 132 | , 133 | "cv2.data": [ # OPENCV_OTHER_INSTALL_PATH 134 | ("etc" if os.name == "nt" else "share/opencv4") + r"/haarcascades/.*\.xml" 135 | ], 136 | "cv2.gapi": [ 137 | "python/cv2" + r"/gapi/.*\.py" 138 | ], 139 | "cv2.mat_wrapper": [ 140 | "python/cv2" + r"/mat_wrapper/.*\.py" 141 | ], 142 | "cv2.misc": [ 143 | "python/cv2" + r"/misc/.*\.py" 144 | ], 145 | "cv2.utils": [ 146 | "python/cv2" + r"/utils/.*\.py" 147 | ], 148 | } 149 | 150 | if sys.version_info >= (3, 6): 151 | rearrange_cmake_output_data["cv2.typing"] = ["python/cv2" + r"/typing/.*\.py"] 152 | 153 | # Files in sourcetree outside package dir that should be copied to package. 154 | # Raw paths relative to sourcetree root. 155 | files_outside_package_dir = {"cv2": ["LICENSE.txt", "LICENSE-3RD-PARTY.txt"]} 156 | 157 | ci_cmake_generator = ( 158 | ["-G", "Visual Studio 17 2022"] 159 | if os.name == "nt" 160 | else ["-G", "Unix Makefiles"] 161 | ) 162 | 163 | cmake_args = ( 164 | (ci_cmake_generator if is_CI_build else []) 165 | + [ 166 | # skbuild inserts PYTHON_* vars. That doesn't satisfy opencv build scripts in case of Py3 167 | "-DPYTHON3_EXECUTABLE=%s" % sys.executable, 168 | "-DPYTHON_DEFAULT_EXECUTABLE=%s" % sys.executable, 169 | "-DPYTHON3_INCLUDE_DIR=%s" % python_include_dir, 170 | "-DPYTHON3_LIBRARY=%s" % python_lib_path, 171 | "-DBUILD_opencv_python3=ON", 172 | "-DBUILD_opencv_python2=OFF", 173 | # Disable the Java build by default as it is not needed 174 | "-DBUILD_opencv_java=%s" % build_java, 175 | # Relative dir to install the built module to in the build tree. 176 | # The default is generated from sysconfig, we'd rather have a constant for simplicity 177 | "-DOPENCV_PYTHON3_INSTALL_PATH=python", 178 | # Otherwise, opencv scripts would want to install `.pyd' right into site-packages, 179 | # and skbuild bails out on seeing that 180 | "-DINSTALL_CREATE_DISTRIB=ON", 181 | # See opencv/CMakeLists.txt for options and defaults 182 | "-DBUILD_opencv_apps=OFF", 183 | "-DBUILD_opencv_freetype=OFF", 184 | "-DBUILD_SHARED_LIBS=OFF", 185 | "-DBUILD_TESTS=OFF", 186 | "-DBUILD_PERF_TESTS=OFF", 187 | "-DBUILD_DOCS=OFF", 188 | "-DPYTHON3_LIMITED_API=ON", 189 | "-DBUILD_OPENEXR=ON", 190 | ] 191 | + ( 192 | # CMake flags for windows/arm64 build 193 | ["-DCMAKE_GENERATOR_PLATFORM=ARM64", 194 | # Emulated cmake requires following flags to correctly detect 195 | # target architecture for windows/arm64 build 196 | "-DOPENCV_WORKAROUND_CMAKE_20989=ON", 197 | "-DCMAKE_SYSTEM_PROCESSOR=ARM64"] 198 | if platform.machine() == "ARM64" and sys.platform == "win32" 199 | # If it is not defined 'linker flags: /machine:X86' on Windows x64 200 | else ["-DCMAKE_GENERATOR_PLATFORM=x64"] if is64 and sys.platform == "win32" 201 | else [] 202 | ) 203 | + ( 204 | ["-DOPENCV_EXTRA_MODULES_PATH=" + os.path.abspath("opencv_contrib/modules")] 205 | if build_contrib 206 | else [] 207 | ) 208 | ) 209 | 210 | if build_headless: 211 | # it seems that cocoa cannot be disabled so on macOS the package is not truly headless 212 | cmake_args.append("-DWITH_WIN32UI=OFF") 213 | cmake_args.append("-DWITH_QT=OFF") 214 | cmake_args.append("-DWITH_GTK=OFF") 215 | # see: https://github.com/skvark/opencv-python/issues/263 216 | # see: https://github.com/opencv/opencv-python/issues/771 217 | cmake_args.append("-DWITH_MSMF=OFF") 218 | cmake_args.append("-DWITH_OBSENSOR=OFF") # Orbbec cameras backend uses MSMF API 219 | 220 | if sys.platform.startswith("linux") and not is64 and "bdist_wheel" in sys.argv: 221 | subprocess.check_call("patch -p0 < patches/patchOpenEXR", shell=True) 222 | 223 | # OS-specific components during CI builds 224 | if is_CI_build: 225 | 226 | if ( 227 | not build_headless 228 | and "bdist_wheel" in sys.argv 229 | and sys.platform.startswith("linux") 230 | ): 231 | cmake_args.append("-DWITH_QT=5") 232 | subprocess.check_call("patch -p1 < patches/patchQtPlugins", shell=True) 233 | 234 | if sys.platform.startswith("linux"): 235 | rearrange_cmake_output_data["cv2.qt.plugins.platforms"] = [ 236 | (r"lib/qt/plugins/platforms/libqxcb\.so") 237 | ] 238 | 239 | # add fonts for Qt5 240 | fonts = [] 241 | for file in os.listdir("/usr/share/fonts/dejavu"): 242 | if file.endswith(".ttf"): 243 | fonts.append( 244 | (r"lib/qt/fonts/dejavu/%s\.ttf" % file.split(".")[0]) 245 | ) 246 | 247 | rearrange_cmake_output_data["cv2.qt.fonts"] = fonts 248 | 249 | if sys.platform == "darwin": 250 | rearrange_cmake_output_data["cv2.qt.plugins.platforms"] = [ 251 | (r"lib/qt/plugins/platforms/libqcocoa\.dylib") 252 | ] 253 | 254 | if sys.platform.startswith("linux"): 255 | cmake_args.append("-DWITH_V4L=ON") 256 | cmake_args.append("-DWITH_LAPACK=ON") 257 | cmake_args.append("-DENABLE_PRECOMPILED_HEADERS=OFF") 258 | 259 | # works via side effect 260 | RearrangeCMakeOutput( 261 | rearrange_cmake_output_data, files_outside_package_dir, package_data.keys() 262 | ) 263 | 264 | setup( 265 | name=package_name, 266 | version=package_version, 267 | url="https://github.com/opencv/opencv-python", 268 | license="Apache 2.0", 269 | description="Wrapper package for OpenCV python bindings.", 270 | long_description=long_description, 271 | long_description_content_type="text/markdown", 272 | packages=packages, 273 | package_data=package_data, 274 | maintainer="OpenCV Team", 275 | ext_modules=EmptyListWithLength(), 276 | install_requires=install_requires, 277 | python_requires=">=3.6", 278 | classifiers=[ 279 | "Development Status :: 5 - Production/Stable", 280 | "Environment :: Console", 281 | "Intended Audience :: Developers", 282 | "Intended Audience :: Education", 283 | "Intended Audience :: Information Technology", 284 | "Intended Audience :: Science/Research", 285 | "License :: OSI Approved :: Apache Software License", 286 | "Operating System :: MacOS", 287 | "Operating System :: Microsoft :: Windows", 288 | "Operating System :: POSIX", 289 | "Operating System :: Unix", 290 | "Programming Language :: Python", 291 | "Programming Language :: Python :: 3", 292 | "Programming Language :: Python :: 3 :: Only", 293 | "Programming Language :: Python :: 3.6", 294 | "Programming Language :: Python :: 3.7", 295 | "Programming Language :: Python :: 3.8", 296 | "Programming Language :: Python :: 3.9", 297 | "Programming Language :: Python :: 3.10", 298 | "Programming Language :: Python :: 3.11", 299 | "Programming Language :: Python :: 3.12", 300 | "Programming Language :: Python :: 3.13", 301 | "Programming Language :: C++", 302 | "Programming Language :: Python :: Implementation :: CPython", 303 | "Topic :: Scientific/Engineering", 304 | "Topic :: Scientific/Engineering :: Image Recognition", 305 | "Topic :: Software Development", 306 | ], 307 | cmake_args=cmake_args, 308 | cmake_source_dir=cmake_source_dir, 309 | ) 310 | 311 | print("OpenCV is raising funds to keep the library free for everyone, and we need the support of the entire community to do it. Donate to OpenCV on GitHub:\nhttps://github.com/sponsors/opencv\n") 312 | 313 | class RearrangeCMakeOutput: 314 | """ 315 | Patch SKBuild logic to only take files related to the Python package 316 | and construct a file hierarchy that SKBuild expects (see below) 317 | """ 318 | 319 | _setuptools_wrap = None 320 | 321 | # Have to wrap a function reference, or it's converted 322 | # into an instance method on attr assignment 323 | import argparse 324 | 325 | wraps = argparse.Namespace(_classify_installed_files=None) 326 | del argparse 327 | 328 | package_paths_re = None 329 | packages = None 330 | files_outside_package = None 331 | 332 | def __init__(self, package_paths_re, files_outside_package, packages): 333 | cls = self.__class__ 334 | assert not cls.wraps._classify_installed_files, "Singleton object" 335 | import skbuild.setuptools_wrap 336 | 337 | cls._setuptools_wrap = skbuild.setuptools_wrap 338 | cls.wraps._classify_installed_files = ( 339 | cls._setuptools_wrap._classify_installed_files 340 | ) 341 | cls._setuptools_wrap._classify_installed_files = ( 342 | self._classify_installed_files_override 343 | ) 344 | 345 | cls.package_paths_re = package_paths_re 346 | cls.files_outside_package = files_outside_package 347 | cls.packages = packages 348 | 349 | def __del__(self): 350 | cls = self.__class__ 351 | cls._setuptools_wrap._classify_installed_files = ( 352 | cls.wraps._classify_installed_files 353 | ) 354 | cls.wraps._classify_installed_files = None 355 | cls._setuptools_wrap = None 356 | 357 | def _classify_installed_files_override( 358 | self, 359 | install_paths, 360 | package_data, 361 | package_prefixes, 362 | py_modules, 363 | new_py_modules, 364 | scripts, 365 | new_scripts, 366 | data_files, 367 | cmake_source_dir, 368 | cmake_install_reldir, 369 | ): 370 | """ 371 | From all CMake output, we're only interested in a few files 372 | and must place them into CMake install dir according 373 | to Python conventions for SKBuild to find them: 374 | package\ 375 | file 376 | subpackage\ 377 | etc. 378 | """ 379 | 380 | cls = self.__class__ 381 | 382 | # 'relpath'/'reldir' = relative to CMAKE_INSTALL_DIR/cmake_install_dir 383 | # 'path'/'dir' = relative to sourcetree root 384 | cmake_install_dir = os.path.join( 385 | cls._setuptools_wrap.CMAKE_INSTALL_DIR(), cmake_install_reldir 386 | ) 387 | install_relpaths = [ 388 | os.path.relpath(p, cmake_install_dir) for p in install_paths 389 | ] 390 | fslash_install_relpaths = [ 391 | p.replace(os.path.sep, "/") for p in install_relpaths 392 | ] 393 | relpaths_zip = list(zip(fslash_install_relpaths, install_relpaths)) 394 | 395 | final_install_relpaths = [] 396 | 397 | print("Copying files from CMake output") 398 | 399 | # add lines from the old __init__.py file to the config file 400 | with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'scripts', '__init__.py'), 'r') as custom_init: 401 | custom_init_data = custom_init.read() 402 | 403 | # OpenCV generates config with different name for case with PYTHON3_LIMITED_API=ON 404 | config_py = os.path.join(cmake_install_dir, 'python', 'cv2', 'config-%s.%s.py' 405 | % (sys.version_info[0], sys.version_info[1])) 406 | if not os.path.exists(config_py): 407 | config_py = os.path.join(cmake_install_dir, 'python', 'cv2', 'config-%s.py' % sys.version_info[0]) 408 | 409 | with open(config_py, 'w') as opencv_init_config: 410 | opencv_init_config.write(custom_init_data) 411 | 412 | if sys.version_info >= (3, 6): 413 | for p in install_relpaths: 414 | if p.endswith(".pyi"): 415 | target_rel_path = os.path.relpath(p, "python/cv2") 416 | cls._setuptools_wrap._copy_file( 417 | os.path.join(cmake_install_dir, p), 418 | os.path.join(cmake_install_dir, "cv2", target_rel_path), 419 | hide_listing=False, 420 | ) 421 | final_install_relpaths.append(os.path.join("cv2", target_rel_path)) 422 | 423 | del install_relpaths, fslash_install_relpaths 424 | 425 | for package_name, relpaths_re in cls.package_paths_re.items(): 426 | package_dest_reldir = package_name.replace(".", os.path.sep) 427 | for relpath_re in relpaths_re: 428 | found = False 429 | r = re.compile(relpath_re + "$") 430 | for fslash_relpath, relpath in relpaths_zip: 431 | m = r.match(fslash_relpath) 432 | if not m: 433 | continue 434 | found = True 435 | new_install_relpath = os.path.join( 436 | package_dest_reldir, os.path.basename(relpath) 437 | ) 438 | cls._setuptools_wrap._copy_file( 439 | os.path.join(cmake_install_dir, relpath), 440 | os.path.join(cmake_install_dir, new_install_relpath), 441 | hide_listing=False, 442 | ) 443 | final_install_relpaths.append(new_install_relpath) 444 | del m, fslash_relpath, new_install_relpath 445 | else: 446 | # gapi can be missed if ADE was not downloaded (network issue) 447 | if not found and "gapi" not in relpath_re: 448 | raise Exception("Not found: '%s'" % relpath_re) 449 | del r, found 450 | 451 | del relpaths_zip 452 | 453 | print("Copying files from non-default sourcetree locations") 454 | 455 | for package_name, paths in cls.files_outside_package.items(): 456 | package_dest_reldir = package_name.replace(".", os.path.sep) 457 | for path in paths: 458 | new_install_relpath = os.path.join( 459 | package_dest_reldir, 460 | # Don't yet have a need to copy 461 | # to subdirectories of package dir 462 | os.path.basename(path), 463 | ) 464 | cls._setuptools_wrap._copy_file( 465 | path, 466 | os.path.join(cmake_install_dir, new_install_relpath), 467 | hide_listing=False, 468 | ) 469 | final_install_relpaths.append(new_install_relpath) 470 | 471 | final_install_paths = [ 472 | os.path.join(cmake_install_dir, p) for p in final_install_relpaths 473 | ] 474 | 475 | return (cls.wraps._classify_installed_files)( 476 | final_install_paths, 477 | package_data, 478 | package_prefixes, 479 | py_modules, 480 | new_py_modules, 481 | scripts, 482 | new_scripts, 483 | data_files, 484 | # To get around a check that prepends source dir to paths and breaks package detection code. 485 | cmake_source_dir="", 486 | _cmake_install_dir=cmake_install_reldir, 487 | ) 488 | 489 | 490 | def get_and_set_info(contrib, headless, rolling, ci_build): 491 | # cv2/version.py should be generated by running find_version.py 492 | version = {} 493 | here = os.path.abspath(os.path.dirname(__file__)) 494 | version_file = os.path.join(here, "cv2", "version.py") 495 | 496 | # generate a fresh version.py always when Git repository exists 497 | # (in sdists the version.py file already exists) 498 | if os.path.exists(".git"): 499 | old_args = sys.argv.copy() 500 | sys.argv = ["", str(contrib), str(headless), str(rolling), str(ci_build)] 501 | runpy.run_path("find_version.py", run_name="__main__") 502 | sys.argv = old_args 503 | 504 | with open(version_file) as fp: 505 | exec(fp.read(), version) 506 | 507 | return version["opencv_version"], version["contrib"], version["headless"], version["rolling"] 508 | 509 | 510 | def get_build_env_var_by_name(flag_name): 511 | flag_set = False 512 | 513 | try: 514 | flag_set = bool(int(os.getenv("ENABLE_" + flag_name.upper(), None))) 515 | except Exception: 516 | pass 517 | 518 | if not flag_set: 519 | try: 520 | flag_set = bool(int(open(flag_name + ".enabled").read(1))) 521 | except Exception: 522 | pass 523 | 524 | return flag_set 525 | 526 | 527 | # This creates a list which is empty but returns a length of 1. 528 | # Should make the wheel a binary distribution and platlib compliant. 529 | class EmptyListWithLength(list): 530 | def __len__(self): 531 | return 1 532 | 533 | 534 | if __name__ == "__main__": 535 | main() 536 | --------------------------------------------------------------------------------