diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml new file mode 100644 index 0000000000..1921e63c22 --- /dev/null +++ b/.github/workflows/build-wheels.yml @@ -0,0 +1,182 @@ +name: Build Python Wheels + +on: + push: + branches: + - master + - add-python-3.13-support + tags: + - 'v*' + pull_request: + branches: + - master + - add-python-3.13-support + workflow_dispatch: + +env: + BAZEL_VERSION: '7.4.1' + PROTOBUF_VERSION: '29' + +jobs: + build-macos-arm64: + name: Build macOS ARM64 wheel (Python ${{ matrix.python-version }}) + runs-on: macos-latest + strategy: + fail-fast: false + matrix: + python-version: ['3.9', '3.10', '3.11', '3.12', '3.13'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v5 + with: + python-version: ${{ matrix.python-version }} + cache: 'pip' + + - name: Cache Bazel + uses: actions/cache@v4 + with: + path: | + ~/.cache/bazel + ~/.cache/bazelisk + key: ${{ runner.os }}-bazel-${{ env.BAZEL_VERSION }}-py${{ matrix.python-version }}-${{ hashFiles('.bazelversion', 'WORKSPACE', '**/*.bzl') }} + restore-keys: | + ${{ runner.os }}-bazel-${{ env.BAZEL_VERSION }}-py${{ matrix.python-version }}- + ${{ runner.os }}-bazel-${{ env.BAZEL_VERSION }}- + ${{ runner.os }}-bazel- + + - name: Cache Homebrew packages + uses: actions/cache@v4 + with: + path: | + ~/Library/Caches/Homebrew/bazelisk--* + ~/Library/Caches/Homebrew/opencv--* + ~/Library/Caches/Homebrew/protobuf@${{ env.PROTOBUF_VERSION }}--* + ~/Library/Caches/Homebrew/downloads/*--bazelisk-* + ~/Library/Caches/Homebrew/downloads/*--opencv-* + ~/Library/Caches/Homebrew/downloads/*--protobuf@${{ env.PROTOBUF_VERSION }}-* + key: ${{ runner.os }}-brew-${{ hashFiles('.github/workflows/build-wheels-py313.yml') }} + restore-keys: | + ${{ runner.os }}-brew- + + - name: Install system dependencies + run: | + # Disable auto-update for faster installs + export HOMEBREW_NO_AUTO_UPDATE=1 + + # Use bazelisk instead of bazel for automatic version management + brew install bazelisk opencv protobuf@${{ env.PROTOBUF_VERSION }} + + - name: Verify system dependencies + id: verify-deps + run: | + echo "=== Bazel ===" + bazel --version + + echo "=== OpenCV ===" + OPENCV_VERSION=$(brew ls opencv | grep version.hpp | head -1 | sed -E 's|.*/opencv/([^/]+)/.*|\1|') + echo "version=$OPENCV_VERSION" >> $GITHUB_OUTPUT + echo "OpenCV version: $OPENCV_VERSION" + + OPENCV_MAJOR_MINOR=$(echo $OPENCV_VERSION | sed -E 's/([0-9]+\.[0-9]+).*/\1/') + echo "major_minor=$OPENCV_MAJOR_MINOR" >> $GITHUB_OUTPUT + echo "OpenCV major.minor: $OPENCV_MAJOR_MINOR" + + echo "=== Protobuf ===" + PROTOC_PATH=/opt/homebrew/opt/protobuf@${{ env.PROTOBUF_VERSION }}/bin/protoc + echo "path=$PROTOC_PATH" >> $GITHUB_OUTPUT + $PROTOC_PATH --version + + echo "=== Python ===" + python --version + pip --version + + - name: Set version + id: set-version + run: | + # Generate version from git commit and date + if [[ "${{ github.ref }}" == refs/tags/* ]]; then + # If triggered by a tag, use the tag name (strip 'v' prefix) + VERSION="${{ github.ref_name }}" + VERSION="${VERSION#v}" + else + # Otherwise, use date-based version with short commit hash + VERSION="0.10.14.dev$(date +%Y%m%d)+g$(git rev-parse --short HEAD)" + fi + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Using version: $VERSION" + + - name: Configure build environment + run: | + # Update OpenCV configuration + sed -i '' "s|PREFIX = \"opencv/.*\"|PREFIX = \"opencv/${{ steps.verify-deps.outputs.version }}\"|" third_party/opencv_macos.BUILD + sed -i '' "s|OPENCV_SO_VERSION = \".*\"|OPENCV_SO_VERSION = \"${{ steps.verify-deps.outputs.major_minor }}\"|" third_party/BUILD + + # Update version in setup.py + sed -i '' "s|__version__ = '.*'|__version__ = '${{ steps.set-version.outputs.version }}'|" setup.py + + echo "Configuration updated:" + grep "PREFIX = " third_party/opencv_macos.BUILD + grep "OPENCV_SO_VERSION = " third_party/BUILD + grep "__version__ = " setup.py + + - name: Install Python dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + # Convert python-version from "3.9" to "3_9" format for lock file + LOCK_VERSION=$(echo "${{ matrix.python-version }}" | tr '.' '_') + pip install -r "requirements_lock_${LOCK_VERSION}.txt" + + - name: Build wheel + env: + HERMETIC_PYTHON_VERSION: ${{ matrix.python-version }} + PROTOC: ${{ steps.verify-deps.outputs.path }} + run: | + echo "::group::Build MediaPipe wheel" + python setup.py bdist_wheel 2>&1 | tee build.log + echo "::endgroup::" + + - name: Verify wheel + run: | + ls -lh dist/ + file dist/*.whl + unzip -l dist/*.whl | head -50 + + - name: Test wheel installation + run: | + python -m venv test_env + source test_env/bin/activate + pip install --upgrade pip + pip install dist/*.whl + + # Change to a different directory to avoid importing from source + cd /tmp + echo "::group::Test imports" + python -c "import mediapipe; print(f'MediaPipe version: {mediapipe.__version__}')" + python -c "import mediapipe.tasks.python.vision as vision; print('Vision tasks: OK')" + python -c "import mediapipe.tasks.python.text as text; print('Text tasks: OK')" + python -c "import mediapipe.tasks.python.audio as audio; print('Audio tasks: OK')" + echo "::endgroup::" + + deactivate + + - name: Upload wheel artifact + uses: actions/upload-artifact@v4 + with: + name: wheel-macos-arm64-py${{ matrix.python-version }} + path: dist/*.whl + retention-days: 90 + if-no-files-found: error + + - name: Upload build log + if: always() + uses: actions/upload-artifact@v4 + with: + name: build-log-macos-arm64-py${{ matrix.python-version }} + path: build.log + retention-days: 30 diff --git a/.gitignore b/.gitignore index 525f0878ef..fe0ccfb879 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,20 @@ mediapipe/provisioning_profile.mobileprovision node_modules/ .configure.bazelrc .user.bazelrc + +# Python build artifacts +build/ +dist/ +*.egg-info/ +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +venv/ +venv_py*/ +*.so +*.dylib +mediapipe/__init__.py.backup +__init__.py +build.log diff --git a/WORKSPACE b/WORKSPACE index 460fb4c57b..d689a938f1 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -118,15 +118,9 @@ http_archive( http_archive( name = "zlib", build_file = "@//third_party:zlib.BUILD", - patch_args = [ - "-p1", - ], - patches = [ - "@//third_party:zlib.diff", - ], - sha256 = "b3a24de97a8fdbc835b9833169501030b8977031bcb54b3b3ac13740f846ab30", - strip_prefix = "zlib-1.2.13", - url = "http://zlib.net/fossils/zlib-1.2.13.tar.gz", + sha256 = "9a93b2b7dfdac77ceba5a558a580e74667dd6fede4585b91eefb60f03b72df23", + strip_prefix = "zlib-1.3.1", + url = "https://zlib.net/fossils/zlib-1.3.1.tar.gz", ) # gflags needed by glog @@ -364,10 +358,11 @@ python_init_repositories( local_wheel_inclusion_list = ["mediapipe*"], local_wheel_workspaces = ["//:WORKSPACE"], requirements = { - "3.9": "//:requirements_lock.txt", + "3.9": "//:requirements_lock_3_9.txt", "3.10": "//:requirements_lock_3_10.txt", "3.11": "//:requirements_lock_3_11.txt", "3.12": "//:requirements_lock_3_12.txt", + "3.13": "//:requirements_lock_3_13.txt", }, ) @@ -400,7 +395,7 @@ load("@rules_python//python:pip.bzl", "pip_parse") pip_parse( name = "mediapipe_pip_deps", - requirements_lock = "@//:requirements_lock.txt", + requirements_lock = "@//:requirements_lock_3_9.txt", ) load("@mediapipe_pip_deps//:requirements.bzl", mp_install_deps = "install_deps") @@ -606,10 +601,10 @@ new_local_repository( new_local_repository( name = "macos_opencv", build_file = "@//third_party:opencv_macos.BUILD", - # For local MacOS builds, the path should point to an opencv@3 installation. + # For local MacOS builds, the path should point to an opencv installation. # If you edit the path here, you will also need to update the corresponding # prefix in "opencv_macos.BUILD". - path = "/usr/local", # e.g. /usr/local/Cellar for HomeBrew + path = "/opt/homebrew/Cellar", ) new_local_repository( diff --git a/mediapipe/python/BUILD b/mediapipe/python/BUILD index 513465439c..346e09ad4a 100644 --- a/mediapipe/python/BUILD +++ b/mediapipe/python/BUILD @@ -32,6 +32,9 @@ pybind_extension( "-lopencv_calib3d", "-lopencv_imgcodecs", ], + }) + select({ + "@bazel_tools//src/conditions:darwin": ["-undefined", "dynamic_lookup"], + "//conditions:default": [], }), module_name = "_framework_bindings", deps = [ @@ -48,7 +51,6 @@ pybind_extension( "//mediapipe/python/pybind:resource_util", "//mediapipe/python/pybind:timestamp", "//mediapipe/python/pybind:validated_graph_config", - "//mediapipe/tasks/python/core/pybind:task_runner", "@com_google_absl//absl/strings:str_format", "@stblib//:stb_image", # Type registration. diff --git a/mediapipe/python/pybind/calculator_graph.cc b/mediapipe/python/pybind/calculator_graph.cc index 8b226a63c8..cf50f23bbc 100644 --- a/mediapipe/python/pybind/calculator_graph.cc +++ b/mediapipe/python/pybind/calculator_graph.cc @@ -438,7 +438,7 @@ void CalculatorGraphSubmodule(pybind11::module* module) { RaisePyErrorIfNotOk(self->ObserveOutputStream( stream_name, [callback_fn, stream_name](const Packet& packet) { - absl::MutexLock lock(callback_mutex); + absl::MutexLock lock(&callback_mutex); // Acquires GIL before calling Python callback. py::gil_scoped_acquire gil_acquire; callback_fn(stream_name, packet); diff --git a/mediapipe/tasks/cc/metadata/python/BUILD b/mediapipe/tasks/cc/metadata/python/BUILD index 6ec6d8ebfd..66552d4276 100644 --- a/mediapipe/tasks/cc/metadata/python/BUILD +++ b/mediapipe/tasks/cc/metadata/python/BUILD @@ -11,6 +11,10 @@ pybind_extension( "metadata_version.cc", ], features = ["-use_header_modules"], + linkopts = select({ + "@bazel_tools//src/conditions:darwin": ["-undefined", "dynamic_lookup"], + "//conditions:default": [], + }), module_name = "_pywrap_metadata_version", deps = [ "//mediapipe/tasks/cc/metadata:metadata_version", diff --git a/mediapipe/tasks/python/text/__init__.py b/mediapipe/tasks/python/text/__init__.py index 66c62cafcb..552e124eff 100644 --- a/mediapipe/tasks/python/text/__init__.py +++ b/mediapipe/tasks/python/text/__init__.py @@ -17,6 +17,7 @@ import mediapipe.tasks.python.text.language_detector import mediapipe.tasks.python.text.text_classifier import mediapipe.tasks.python.text.text_embedder +from mediapipe.tasks.python.components.containers import embedding_result LanguageDetector = language_detector.LanguageDetector LanguageDetectorOptions = language_detector.LanguageDetectorOptions @@ -26,10 +27,11 @@ TextClassifierResult = text_classifier.TextClassifierResult TextEmbedder = text_embedder.TextEmbedder TextEmbedderOptions = text_embedder.TextEmbedderOptions -TextEmbedderResult = text_embedder.TextEmbedderResult +TextEmbedderResult = embedding_result.EmbeddingResult # Remove unnecessary modules to avoid duplication in API docs. del mediapipe del language_detector del text_classifier del text_embedder +del embedding_result diff --git a/mediapipe/tasks/python/vision/__init__.py b/mediapipe/tasks/python/vision/__init__.py index a5b2080b58..ac1e954052 100644 --- a/mediapipe/tasks/python/vision/__init__.py +++ b/mediapipe/tasks/python/vision/__init__.py @@ -18,6 +18,7 @@ import mediapipe.tasks.python.vision.face_detector import mediapipe.tasks.python.vision.face_landmarker import mediapipe.tasks.python.vision.gesture_recognizer +import mediapipe.tasks.python.vision.gesture_recognizer_result import mediapipe.tasks.python.vision.hand_landmarker import mediapipe.tasks.python.vision.image_classifier import mediapipe.tasks.python.vision.image_embedder @@ -35,7 +36,7 @@ FaceLandmarksConnections = face_landmarker.FaceLandmarksConnections GestureRecognizer = gesture_recognizer.GestureRecognizer GestureRecognizerOptions = gesture_recognizer.GestureRecognizerOptions -GestureRecognizerResult = gesture_recognizer.GestureRecognizerResult +GestureRecognizerResult = gesture_recognizer_result.GestureRecognizerResult HandLandmarker = hand_landmarker.HandLandmarker HandLandmarkerOptions = hand_landmarker.HandLandmarkerOptions HandLandmarkerResult = hand_landmarker.HandLandmarkerResult @@ -67,6 +68,7 @@ del face_detector del face_landmarker del gesture_recognizer +del gesture_recognizer_result del hand_landmarker del image_classifier del image_embedder diff --git a/requirements.txt b/requirements.txt index c142979c49..e24c90e7f8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,14 @@ -absl-py~=2.3 -numpy -sounddevice~=0.5 -flatbuffers~=25.9 +absl-py +attrs>=19.1.0 +flatbuffers>=2.0 +jax +jaxlib +matplotlib +numpy<2; python_version < "3.13" +numpy; python_version >= "3.13" +opencv-contrib-python<4.12; python_version < "3.13" +opencv-contrib-python; python_version >= "3.13" +protobuf>=5.29.3,<6 +sounddevice>=0.4.4 +sentencepiece>=0.2.1; python_version >= "3.13" +sentencepiece; python_version < "3.13" diff --git a/requirements_lock.txt b/requirements_lock.txt deleted file mode 100644 index f3a55e31a4..0000000000 --- a/requirements_lock.txt +++ /dev/null @@ -1,78 +0,0 @@ -# -# This file is autogenerated by pip-compile with Python 3.9 -# by the following command: -# -# pip-compile --output-file=mediapipe/opensource_only/requirements_lock.txt mediapipe/opensource_only/requirements.txt -# -absl-py==2.1.0 - # via -r mediapipe/opensource_only/requirements.txt -attrs==24.2.0 - # via -r mediapipe/opensource_only/requirements.txt -cffi==1.17.1 - # via sounddevice -contourpy==1.3.0 - # via matplotlib -cycler==0.12.1 - # via matplotlib -flatbuffers==24.3.25 - # via -r mediapipe/opensource_only/requirements.txt -fonttools==4.54.1 - # via matplotlib -importlib-metadata==8.5.0 - # via jax -importlib-resources==6.4.5 - # via matplotlib -jax==0.4.30 - # via -r mediapipe/opensource_only/requirements.txt -jaxlib==0.4.30 - # via - # -r mediapipe/opensource_only/requirements.txt - # jax -kiwisolver==1.4.7 - # via matplotlib -matplotlib==3.9.2 - # via -r mediapipe/opensource_only/requirements.txt -ml-dtypes==0.5.0 - # via - # jax - # jaxlib -numpy==1.26.4 - # via - # -r mediapipe/opensource_only/requirements.txt - # contourpy - # jax - # jaxlib - # matplotlib - # ml-dtypes - # opencv-contrib-python - # scipy -opencv-contrib-python==4.10.0.84 - # via -r mediapipe/opensource_only/requirements.txt -opt-einsum==3.4.0 - # via jax -packaging==24.1 - # via matplotlib -pillow==10.4.0 - # via matplotlib -protobuf==4.25.5 - # via -r mediapipe/opensource_only/requirements.txt -pycparser==2.22 - # via cffi -pyparsing==3.1.4 - # via matplotlib -python-dateutil==2.9.0.post0 - # via matplotlib -scipy==1.13.1 - # via - # jax - # jaxlib -sentencepiece==0.2.0 - # via -r mediapipe/opensource_only/requirements.txt -six==1.16.0 - # via python-dateutil -sounddevice==0.5.0 - # via -r mediapipe/opensource_only/requirements.txt -zipp==3.20.2 - # via - # importlib-metadata - # importlib-resources diff --git a/requirements_lock_3_10.txt b/requirements_lock_3_10.txt index c393c0183c..346849e870 100644 --- a/requirements_lock_3_10.txt +++ b/requirements_lock_3_10.txt @@ -2,12 +2,12 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --output-file=mediapipe/opensource_only/requirements_lock_3_10.txt mediapipe/opensource_only/requirements.txt +# pip-compile --output-file=requirements_lock_3_10.txt --strip-extras requirements.txt # absl-py==2.1.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt attrs==24.2.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt cffi==1.17.1 # via sounddevice contourpy==1.3.0 @@ -15,26 +15,26 @@ contourpy==1.3.0 cycler==0.12.1 # via matplotlib flatbuffers==24.3.25 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt fonttools==4.54.1 # via matplotlib jax==0.4.30 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt jaxlib==0.4.30 # via - # -r mediapipe/opensource_only/requirements.txt + # -r requirements.txt # jax kiwisolver==1.4.7 # via matplotlib matplotlib==3.9.2 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt ml-dtypes==0.5.0 # via # jax # jaxlib -numpy==1.26.4 +numpy==1.26.4 ; python_version < "3.13" # via - # -r mediapipe/opensource_only/requirements.txt + # -r requirements.txt # contourpy # jax # jaxlib @@ -42,16 +42,16 @@ numpy==1.26.4 # ml-dtypes # opencv-contrib-python # scipy -opencv-contrib-python==4.10.0.84 - # via -r mediapipe/opensource_only/requirements.txt +opencv-contrib-python==4.11.0.86 ; python_version < "3.13" + # via -r requirements.txt opt-einsum==3.4.0 # via jax packaging==24.1 # via matplotlib pillow==10.4.0 # via matplotlib -protobuf==4.25.5 - # via -r mediapipe/opensource_only/requirements.txt +protobuf==5.29.5 + # via -r requirements.txt pycparser==2.22 # via cffi pyparsing==3.1.4 @@ -63,8 +63,8 @@ scipy==1.13.1 # jax # jaxlib sentencepiece==0.2.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt six==1.16.0 # via python-dateutil sounddevice==0.5.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt diff --git a/requirements_lock_3_11.txt b/requirements_lock_3_11.txt index a1614f51b8..010d24044b 100644 --- a/requirements_lock_3_11.txt +++ b/requirements_lock_3_11.txt @@ -2,12 +2,12 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --output-file=mediapipe/opensource_only/requirements_lock_3_11.txt mediapipe/opensource_only/requirements.txt +# pip-compile --output-file=requirements_lock_3_11.txt requirements.txt # absl-py==2.1.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt attrs==24.2.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt cffi==1.17.1 # via sounddevice contourpy==1.3.0 @@ -15,26 +15,26 @@ contourpy==1.3.0 cycler==0.12.1 # via matplotlib flatbuffers==24.3.25 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt fonttools==4.54.1 # via matplotlib jax==0.4.30 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt jaxlib==0.4.30 # via - # -r mediapipe/opensource_only/requirements.txt + # -r requirements.txt # jax kiwisolver==1.4.7 # via matplotlib matplotlib==3.9.2 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt ml-dtypes==0.5.0 # via # jax # jaxlib numpy==1.26.4 # via - # -r mediapipe/opensource_only/requirements.txt + # -r requirements.txt # contourpy # jax # jaxlib @@ -42,16 +42,16 @@ numpy==1.26.4 # ml-dtypes # opencv-contrib-python # scipy -opencv-contrib-python==4.10.0.84 - # via -r mediapipe/opensource_only/requirements.txt +opencv-contrib-python==4.11.0.86 ; python_version < "3.13" + # via -r requirements.txt opt-einsum==3.4.0 # via jax packaging==24.1 # via matplotlib pillow==10.4.0 # via matplotlib -protobuf==4.25.5 - # via -r mediapipe/opensource_only/requirements.txt +protobuf==5.29.5 + # via -r requirements.txt pycparser==2.22 # via cffi pyparsing==3.1.4 @@ -63,8 +63,8 @@ scipy==1.13.1 # jax # jaxlib sentencepiece==0.2.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt six==1.16.0 # via python-dateutil sounddevice==0.5.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt diff --git a/requirements_lock_3_12.txt b/requirements_lock_3_12.txt index 670db3e888..e6c15e77fc 100644 --- a/requirements_lock_3_12.txt +++ b/requirements_lock_3_12.txt @@ -2,12 +2,12 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --output-file=mediapipe/opensource_only/requirements_lock_3_12.txt mediapipe/opensource_only/requirements.txt +# pip-compile --output-file=requirements_lock_3_12.txt --strip-extras requirements.txt # absl-py==2.1.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt attrs==24.2.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt cffi==1.17.1 # via sounddevice contourpy==1.3.0 @@ -15,26 +15,26 @@ contourpy==1.3.0 cycler==0.12.1 # via matplotlib flatbuffers==24.3.25 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt fonttools==4.54.1 # via matplotlib jax==0.4.30 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt jaxlib==0.4.30 # via - # -r mediapipe/opensource_only/requirements.txt + # -r requirements.txt # jax kiwisolver==1.4.7 # via matplotlib matplotlib==3.9.2 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt ml-dtypes==0.5.0 # via # jax # jaxlib -numpy==1.26.4 +numpy==1.26.4 ; python_version < "3.13" # via - # -r mediapipe/opensource_only/requirements.txt + # -r requirements.txt # contourpy # jax # jaxlib @@ -42,16 +42,16 @@ numpy==1.26.4 # ml-dtypes # opencv-contrib-python # scipy -opencv-contrib-python==4.10.0.84 - # via -r mediapipe/opensource_only/requirements.txt +opencv-contrib-python==4.11.0.86 ; python_version < "3.13" + # via -r requirements.txt opt-einsum==3.4.0 # via jax packaging==24.1 # via matplotlib pillow==10.4.0 # via matplotlib -protobuf==4.25.5 - # via -r mediapipe/opensource_only/requirements.txt +protobuf==5.29.5 + # via -r requirements.txt pycparser==2.22 # via cffi pyparsing==3.1.4 @@ -63,8 +63,8 @@ scipy==1.13.1 # jax # jaxlib sentencepiece==0.2.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt six==1.16.0 # via python-dateutil sounddevice==0.5.0 - # via -r mediapipe/opensource_only/requirements.txt + # via -r requirements.txt diff --git a/requirements_lock_3_13.txt b/requirements_lock_3_13.txt new file mode 100644 index 0000000000..0d6239fca2 --- /dev/null +++ b/requirements_lock_3_13.txt @@ -0,0 +1,70 @@ +# +# This file is autogenerated by pip-compile with Python 3.13 +# by the following command: +# +# pip-compile --output-file=requirements_lock_3_13.txt requirements.txt +# +absl-py==2.1.0 + # via -r requirements.txt +attrs==24.2.0 + # via -r requirements.txt +cffi==1.17.1 + # via sounddevice +contourpy==1.3.0 + # via matplotlib +cycler==0.12.1 + # via matplotlib +flatbuffers==24.3.25 + # via -r requirements.txt +fonttools==4.54.1 + # via matplotlib +jax==0.5.3 + # via -r requirements.txt +jaxlib==0.5.3 + # via + # -r requirements.txt + # jax +kiwisolver==1.4.7 + # via matplotlib +matplotlib==3.9.2 + # via -r requirements.txt +ml-dtypes==0.4.1 + # via + # jax + # jaxlib +numpy==2.2.6 ; python_version >= "3.13" + # via + # -r requirements.txt + # contourpy + # jax + # jaxlib + # matplotlib + # ml-dtypes + # opencv-contrib-python + # scipy +opencv-contrib-python==4.12.0.88 ; python_version >= "3.13" + # via -r requirements.txt +opt-einsum==3.4.0 + # via jax +packaging==24.1 + # via matplotlib +pillow==10.4.0 + # via matplotlib +protobuf==5.29.5 + # via -r requirements.txt +pycparser==2.22 + # via cffi +pyparsing==3.1.4 + # via matplotlib +python-dateutil==2.9.0.post0 + # via matplotlib +scipy==1.16.3 + # via + # jax + # jaxlib +sentencepiece==0.2.1 ; python_version >= "3.13" + # via -r requirements.txt +six==1.16.0 + # via python-dateutil +sounddevice==0.5.0 + # via -r requirements.txt diff --git a/requirements_lock_3_9.txt b/requirements_lock_3_9.txt new file mode 100644 index 0000000000..873d1eff16 --- /dev/null +++ b/requirements_lock_3_9.txt @@ -0,0 +1,78 @@ +# +# This file is autogenerated by pip-compile with Python 3.9 +# by the following command: +# +# pip-compile --output-file=requirements_lock_3_9.txt --strip-extras requirements.txt +# +absl-py==2.3.1 + # via -r requirements.txt +attrs==25.4.0 + # via -r requirements.txt +cffi==2.0.0 + # via sounddevice +contourpy==1.3.0 + # via matplotlib +cycler==0.12.1 + # via matplotlib +flatbuffers==25.9.23 + # via -r requirements.txt +fonttools==4.60.1 + # via matplotlib +importlib-metadata==8.7.0 + # via jax +importlib-resources==6.5.2 + # via matplotlib +jax==0.4.30 + # via -r requirements.txt +jaxlib==0.4.30 + # via + # -r requirements.txt + # jax +kiwisolver==1.4.7 + # via matplotlib +matplotlib==3.9.4 + # via -r requirements.txt +ml-dtypes==0.5.4 + # via + # jax + # jaxlib +numpy==1.26.4 ; python_version < "3.13" + # via + # -r requirements.txt + # contourpy + # jax + # jaxlib + # matplotlib + # ml-dtypes + # opencv-contrib-python + # scipy +opencv-contrib-python==4.11.0.86 ; python_version < "3.13" + # via -r requirements.txt +opt-einsum==3.4.0 + # via jax +packaging==25.0 + # via matplotlib +pillow==11.3.0 + # via matplotlib +protobuf==5.29.5 + # via -r requirements.txt +pycparser==2.23 + # via cffi +pyparsing==3.2.5 + # via matplotlib +python-dateutil==2.9.0.post0 + # via matplotlib +scipy==1.13.1 + # via + # jax + # jaxlib +sentencepiece==0.2.1 + # via -r requirements.txt +six==1.17.0 + # via python-dateutil +sounddevice==0.5.3 + # via -r requirements.txt +zipp==3.23.0 + # via + # importlib-metadata + # importlib-resources diff --git a/setup.py b/setup.py index 2c9d3b8506..e50ec2ac29 100644 --- a/setup.py +++ b/setup.py @@ -256,10 +256,15 @@ def _build_binary(self, ext, extra_args=None): str(ext.bazel_target), ] + GPU_OPTIONS + # Don't override PYTHON_BIN_PATH if HERMETIC_PYTHON_VERSION is set + if not os.environ.get('HERMETIC_PYTHON_VERSION'): + bazel_command.insert(5, '--action_env=PYTHON_BIN_PATH=' + _normalize_path(sys.executable)) + if extra_args: bazel_command += extra_args - if not self.link_opencv and not IS_WINDOWS: - bazel_command.append('--define=OPENCV=source') + # Using system OpenCV instead of building from source + # if not self.link_opencv and not IS_WINDOWS: + # bazel_command.append('--define=OPENCV=source') _invoke_shell_command(bazel_command) @@ -417,6 +422,7 @@ def run(self): 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: 3 :: Only', 'Topic :: Scientific/Engineering', 'Topic :: Scientific/Engineering :: Artificial Intelligence', diff --git a/third_party/BUILD b/third_party/BUILD index 2ab0a7d00e..4358c8b147 100644 --- a/third_party/BUILD +++ b/third_party/BUILD @@ -26,10 +26,11 @@ package(default_visibility = ["//visibility:public"]) exports_files([ "LICENSE", - "requirements_lock.txt", + "requirements_lock_3_9.txt", "requirements_lock_3_10.txt", "requirements_lock_3_11.txt", "requirements_lock_3_12.txt", + "requirements_lock_3_13.txt", ]) mediapipe_files(srcs = [ diff --git a/third_party/opencv_macos.BUILD b/third_party/opencv_macos.BUILD index 4139f188e7..29b6abf04f 100644 --- a/third_party/opencv_macos.BUILD +++ b/third_party/opencv_macos.BUILD @@ -21,21 +21,26 @@ exports_files(["LICENSE"]) # "opencv/3.4.16_10" for the example above). # # # OpenCV 4 -# To configure OpenCV 4, obtain the path of OpenCV 4 from Homebrew. The -# following commands show the output of the command with version 4.10.0_12: +# To configure OpenCV 4, first install it via Homebrew: +# +# $ brew install opencv +# +# Then obtain the version and path of OpenCV 4 from Homebrew: # # $ brew ls opencv | grep version.hpp -# $ /opt/homebrew/Cellar/opencv/4.10.0_12/include/opencv4/opencv2/core/version.hpp -# $ /opt/homebrew/Cellar/opencv/4.10.0_12/include/opencv4/opencv2/dnn/version.hpp +# /opt/homebrew/Cellar/opencv/4.12.0_15/include/opencv4/opencv2/core/version.hpp +# /opt/homebrew/Cellar/opencv/4.12.0_15/include/opencv4/opencv2/dnn/version.hpp # -# Then set path in "macos_opencv" rule in the WORKSPACE file to -# "/opt/homebrew/Cellar" and the PREFIX below to "opencv/" (e.g. -# "opencv/4.10.0_12" for the example above). For OpenCV 4, you will also need to -# adjust the include paths. The header search path should be -# "include/opencv4/opencv2/**/*.h*" and the include prefix needs to be set to -# "include/opencv4". +# Set the path in "macos_opencv" rule in the WORKSPACE file to +# "/opt/homebrew/Cellar" and update the PREFIX below to "opencv/" (e.g. +# "opencv/4.12.0_15" for the example above). +# +# Note: OpenCV 4 has a different header structure than OpenCV 3: +# - Headers are in "include/opencv4/opencv2/**/*.h*" (not "include/opencv2") +# - The include prefix must be set to "include/opencv4" (not "include") +# - This allows #include to resolve correctly -PREFIX = "opt/opencv@3" +PREFIX = "opencv/4.12.0_15" cc_library( name = "opencv", @@ -51,8 +56,8 @@ cc_library( paths.join(PREFIX, "lib/libopencv_videoio.dylib"), ], ), - hdrs = glob([paths.join(PREFIX, "include/opencv2/**/*.h*")]), - includes = [paths.join(PREFIX, "include/")], + hdrs = glob([paths.join(PREFIX, "include/opencv4/opencv2/**/*.h*")]), + includes = [paths.join(PREFIX, "include/opencv4")], linkstatic = 1, visibility = ["//visibility:public"], )