Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ x-references:
build_config: &build_config
docker:
- image: cimg/python:3.8
# resource_class: medium
shell: /bin/bash -eo pipefail
working_directory: ~/vsi
environment:
Expand Down Expand Up @@ -91,7 +92,7 @@ commands:
command: |

# array of available blueprint services to build
BLUEPRINT_SERVICES=( gdal pdal nglog s2 tinycudann )
BLUEPRINT_SERVICES=( gdal pdal nglog s2 tinycudann open3d )

# array of test services
TEST_SERVICES=()
Expand Down
70 changes: 70 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,76 @@ A container using the tinu-cuda-nn wheel must have appropriate versions of pytor
import torch
import tinycudann

Python bindings for open3d
--------------------------

.. code-block:: yaml

services:

open3d:
build:
context: "${VSI_COMMON_DIR}/docker/blueprints"
dockerfile: blueprint_open3d.Dockerfile
args:
# BUILD_CUDA_MODULE: ON|OFF
# https://www.open3d.org/docs/release/compilation.html#:~:text=To%20build%20Open3D%20with%20CUDA%20support%2C%20configure%20with%3A
# CMAKE_CUDA_ARCHITECTURES: 86-real
# https://cmake.org/cmake/help/latest/prop_tgt/CUDA_ARCHITECTURES.html#prop_tgt:CUDA_ARCHITECTURES
# CUDA_VERSION: "12.9.1"
# https://hub.docker.com/r/nvidia/cuda/tags
# OPEN3D_VERSION: "v2.0"
# https://github.com/isl-org/Open3D/releases
# PYTHON_VERSION: "3.13.12"
# https://www.python.org/doc/versions/
# VSI_RECIPE_REPO: "vsiri/recipe"
# https://hub.docker.com/r/vsiri/recipe
image: &open3d_image
example/project:open3d

example:
build:
context: .
dockerfile: example.Dockerfile
args:
OPEN3D_IMAGE: *open3d_image
image: example/project:example

========== ======================= ====
Name Open3D
Output dir ``/usr/local``
Build Args ``BASE_IMAGE`` Base image to build the wheel in. Defaults to ``manylinux_2_28_x86_64``
.. ``BUILD_CUDA_MODULE`` Build Open3D cuda module
.. ``CMAKE_CUDA_ARCHITECTURES`` Build Open3D for these CUDA architectures
.. ``CUDA_VERSION`` Build Open3D for this CUDA version
.. ``OPEN3D_VERSION`` Open3D version to build from source
.. ``PYTHON_VERSION`` Build Open3D for this python version
.. ``VSI_RECIPE_REPO`` VSI docker recipe repo
========== ======================= ====

Compiles the Open3D wheel for use in python. See [github repo](https://github.com/isl-org/Open3D) for usage details.

A container using the CUDA enabled Open3D wheel must have appropriate versions of CUDA installed.

.. code-block:: Dockerfile

# global arguments
ARG OPEN3D_IMAGE
FROM ${OPEN3D_IMAGE} AS open3d

FROM some_image

...

COPY --from=open3d /usr/local /usr/local

RUN pip install /usr/local/share/just/wheels/*
# Or using pip-tools, add "--find-links /usr/local/share/just/wheels" to requirements.in

.. code-block:: example.py

import open3d

---------------------
Blueprint maintenance
---------------------
Expand Down
165 changes: 165 additions & 0 deletions blueprint_open3d.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
# syntax=docker/dockerfile:1.4

ARG BASE_IMAGE="quay.io/pypa/manylinux_2_28_x86_64:2025.09.28-1"
ARG VSI_RECIPE_REPO="vsiri/recipe"

# docker recipes
FROM ${VSI_RECIPE_REPO}:cuda AS cuda

# main builder stage
FROM ${BASE_IMAGE} AS builder

# update shell
SHELL ["/usr/bin/env", "/bin/bash", "-euxvc"]

# install CUDA
ARG CUDA_RECIPE_TARGET="devel"
COPY --from=cuda /usr/local /usr/local
RUN shopt -s nullglob; for patch in /usr/local/share/just/container_build_patch/*; do "${patch}"; done

# dependencies
RUN dnf install -y \
libXcursor-devel \
libXinerama-devel \
libXi-devel \
libxkbcommon-devel \
libXrandr-devel \
mesa-libGLU-devel \
wayland-devel \
# could be used to speed build via USE_SYSTEM_* cmake options,
# however open3d seems to use a lot of custom versions/patches
# libcurl-devel \
# libjpeg-turbo-devel \
# openssl-devel \
; \
rm -rf /var/cache/dnf/*

# clone
ARG OPEN3D_VERSION="v0.19.0"
RUN git clone https://github.com/isl-org/Open3D.git /open3d/source; \
git -C /open3d/source checkout "${OPEN3D_VERSION}";

# workarounds
RUN cd /open3d/source; \
# remove Development.Embed from find_package(python)
sed -i 's|COMPONENTS Interpreter Development)|COMPONENTS Interpreter Development.Module)|g' \
./CMakeLists.txt; \
# stdgpu library directory
sed -i 's|/lib|/lib64|g' ./3rdparty/stdgpu/stdgpu.cmake; \
# remove "-DPYTHON_EXTRA_LIBRARIES" as this will be handled by auditwheel
sed -i 's/^[^#]*-DPYTHON_EXTRA_LIBRARIES/#&/' \
./cpp/pybind/CMakeLists.txt; \
# additionally print openssl in configuration summary
sed -i 's/ZeroMQ/ZeroMQ openssl/g' \
./cmake/Open3DPrintConfigurationSummary.cmake; \
# avoid "open3d-cpu" even when building without GPU capabilities
sed -i 's/name += "-cpu"/#&/g' ./python/setup.py; \
# don't artifically name the python wheel "manylinux"
sed -i 's/plat = f"manylinux/#&/g' ./python/setup.py; \
# complete!
echo "workarounds complete";

# python venv
ARG PYTHON_VERSION="3.13.12"
RUN \
# manylinux python directory
python_major=${PYTHON_VERSION%%.*}; \
python_minor=${PYTHON_VERSION#*.}; \
python_minor=${python_minor%%.*}; \
python_dir=("/opt/python/cp${python_major}${python_minor}-"cp*[0-9m]); \
#
# create python venv & add build dependencies
"${python_dir}/bin/python3" -m venv /venv; \
source /venv/bin/activate; \
pip install \
ninja \
setuptools \
# avoid CMAKE_POLICY_VERSION_MINIMUM issues for 3rd party dependencies
"cmake<4" \
# USE_SYSTEM_PYBIND11 cmake option
# note pybind11 3.0 appears to require open3d>0.19.0
"pybind11[global]<3" \
;

# build twice - once for CPU, once for GPU
# https://github.com/isl-org/Open3D/issues/4371#issuecomment-985943887
#
# Note the two builds don't play well with BUILD_SHARED_LIBS=ON, as both cpu
# and gpu builds produce identically named libopen3d.so files with different
# capabilities, but only one gets loaded at runtime.
#
# set BUILD_CUDA_MODULE=ON to build cuda capabilities. Note this will
# increase the installed python package size by nearly 1GB.
# Use CMAKE_CUDA_ARCHITECTURES to control the CUDA architectures.

# setup
RUN \
# create build directory
mkdir -p /open3d/build; \
# common cmake options saved to disk
CMAKE_COMMON_OPTS=( \
-S /open3d/source \
# -B /open3d/build \
-G Ninja \
-D BUILD_GUI=OFF \
-D BUILD_WEBRTC=OFF \
-D BUILD_EXAMPLES=OFF \
# disable hash on build version
-D DEVELOPER_BUILD=OFF \
# python options
-D BUILD_PYTHON_MODULE=ON \
-D Python3_ROOT=/venv \
# system packages to speed build process
# see notes above regarding adding these system packages
# -D USE_SYSTEM_CURL=ON \
# -D USE_SYSTEM_JPEG=ON \
# -D USE_SYSTEM_OPENSSL=ON \
-D USE_SYSTEM_PYBIND11=ON \
); \
declare -p CMAKE_COMMON_OPTS > /open3d/common.sh

# CPU build
ARG NINJA_BUILD_CONCURRENCY=
RUN cd /open3d/build; \
source /venv/bin/activate; \
source /open3d/common.sh; \
cmake "${CMAKE_COMMON_OPTS[@]}" | tee -a /open3d/config-cpu.log; \
ninja ${NINJA_BUILD_CONCURRENCY:+ -j${NINJA_BUILD_CONCURRENCY}};

# GPU build
ARG BUILD_CUDA_MODULE=OFF
ARG CMAKE_CUDA_ARCHITECTURES=86-real

RUN if [ "${BUILD_CUDA_MODULE}" == "ON" ]; then \
cd /open3d/build; \
source /venv/bin/activate; \
source /open3d/common.sh; \
cmake \
"${CMAKE_COMMON_OPTS[@]}" \
-D CMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc \
-D BUILD_CUDA_MODULE=ON \
-D CMAKE_CUDA_ARCHITECTURES="${CMAKE_CUDA_ARCHITECTURES}" \
| tee -a /open3d/config-gpu.log; \
ninja ${NINJA_BUILD_CONCURRENCY:+ -j${NINJA_BUILD_CONCURRENCY}}; \
fi;

# build `pip-package` cmake target to create base python wheel
RUN source /venv/bin/activate; \
cd /open3d/build; \
ninja pip-package ${NINJA_BUILD_CONCURRENCY:+ -j${NINJA_BUILD_CONCURRENCY}};

# auditwheel
RUN \
# add libtbb.so to LD_LIBRARY_PATH
TBB_SO="$(find /open3d/build -name 'libtbb.so' | head -n1)"; \
TBB_LIBRARY_PATH="$(dirname "${TBB_SO}")"; \
export LD_LIBRARY_PATH="${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}:}${TBB_LIBRARY_PATH}"; \
# auditwheel
mkdir -p /wheelhouse; \
SOURCE_WHEEL="$(find /open3d/build -type f -name '*.whl' | head -n1)"; \
auditwheel repair "${SOURCE_WHEEL}" -w /wheelhouse;

# final wheel in clean environment
FROM scratch

COPY --from=builder /wheelhouse /usr/local/share/just/wheels
15 changes: 15 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,18 @@ services:
# TORCH_VERSION: "${TORCH_VERSION}"
# VSI_RECIPE_REPO: "${VSI_RECIPE_REPO}"
image: vsiri/blueprint:tinycudann

# Example
open3d:
build:
context: .
dockerfile: blueprint_open3d.Dockerfile
args:
# BASE_IMAGE: "${BASE_IMAGE}"
# BUILD_CUDA_MODULE: ON|OFF
# CMAKE_CUDA_ARCHITECTURES: 86-real
CUDA_VERSION: "12.9.1"
# OPEN3D_VERSION: "${OPEN3D_VERSION}"
# PYTHON_VERSION: "${PYTHON_VERSION}"
# VSI_RECIPE_REPO: "${VSI_RECIPE_REPO}"
image: vsiri/blueprint:open3d
24 changes: 24 additions & 0 deletions tests/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ x-args:
TINYCUDANN_VERSION: "v2.0"
TCNN_CUDA_ARCHITECTURES: "70,86"
TORCH_VERSION: &tinycudann_torch_version "2.9.1+cu129"
oepn3d: &open3d_args
BUILD_CUDA_MODULE: OFF
CMAKE_CUDA_ARCHITECTURES: 86-real
CUDA_VERSION: &open3d_cuda_version "12.9.1"
OPEN3D_VERSION: "v0.19.0"
PYTHON_VERSION: &open3d_python_version "3.13.12"

services:

Expand Down Expand Up @@ -65,6 +71,14 @@ services:
<<: *tinycudann_args
image: &tinycudann_image vsiri/blueprint_test:tinycudann

open3d:
build:
context: ..
dockerfile: blueprint_open3d.Dockerfile
args:
<<: *open3d_args
image: &open3d_image vsiri/blueprint_test:open3d

test_gdal:
build:
context: .
Expand Down Expand Up @@ -114,3 +128,13 @@ services:
PYTHON_VERSION: *tinycudann_python_version
TORCH_VERSION: *tinycudann_torch_version
image: vsiri/blueprint_test:test_tinycudann

test_open3d:
build:
context: .
dockerfile: test_open3d.Dockerfile
args:
OPEN3D_IMAGE: *open3d_image
CUDA_VERSION: *open3d_cuda_version
PYTHON_VERSION: *open3d_python_version
image: vsiri/blueprint_test:test_open3d
45 changes: 45 additions & 0 deletions tests/test-open3d.bsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env bash

if [ -z "${VSI_COMMON_DIR+set}" ]; then
VSI_COMMON_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.."; pwd)"
fi

source "${VSI_COMMON_DIR}/tests/testlib.bsh"
source "${VSI_COMMON_DIR}/tests/test_utils.bsh"

: ${DOCKER=docker}

if ! command -v "${DOCKER}" &> /dev/null; then
skip_next_test
fi
begin_test "open3d"
(
setup_test

DOCKER_IMAGE="vsiri/blueprint_test:test_open3d"

function load_open3d()
{
local script="if True:
import open3d
print(open3d.__version__)
mesh = open3d.geometry.TriangleMesh.create_sphere()
mesh.compute_vertex_normals()
print(mesh)
"
local opts=(
--rm
# --env LD_LIBRARY_PATH='/usr/local/cuda-12.9/compat'
--entrypoint ""
"${DOCKER_IMAGE}"
/venv/bin/python -c "${script}"
)
local result="$("${DOCKER}" run "${opts[@]}")"
echo "${result}"
}

RESULT="$(load_open3d)"
EXPECTED="$(echo -e "0.19.0\nTriangleMesh with 762 points and 1520 triangles.")"
assert_str_eq "${RESULT}" "${EXPECTED}"
)
end_test
Loading