Skip to content

Commit 23d662c

Browse files
authored
Merge pull request #3 from nasa/cibuildwheel
Build python wheels with cibuildwheel. Will wait to publish to PyPI until pulling in python unit tests (separate ticket). For now, results are saved as GHA artifacts.
2 parents 1a48470 + 808964d commit 23d662c

19 files changed

+426
-377
lines changed

.github/workflows/build-wheels.yml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
name: Build
2+
3+
on:
4+
push:
5+
workflow_dispatch:
6+
7+
jobs:
8+
build_wheels:
9+
name: ${{ matrix.os }}-${{ github.workflow }}
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
include:
15+
- os: ubuntu-latest
16+
# tag '2023.04.15'
17+
vcpkgCommitId: '501db0f17ef6df184fcdbfbe0f87cde2313b6ab1'
18+
triplet: 'x64-linux-dynamic'
19+
- os: macos-latest
20+
# tag '2023.04.15'
21+
vcpkgCommitId: '501db0f17ef6df184fcdbfbe0f87cde2313b6ab1'
22+
triplet: 'x64-osx-dynamic'
23+
- os: windows-latest
24+
# tag '2023.04.15'
25+
vcpkgCommitId: '501db0f17ef6df184fcdbfbe0f87cde2313b6ab1'
26+
triplet: 'x64-windows'
27+
28+
env:
29+
VCPKG_DEFAULT_TRIPLET: ${{ matrix.triplet }}
30+
31+
steps:
32+
- uses: actions/checkout@v3
33+
with:
34+
fetch-depth: 0
35+
36+
# Special case: cibuildwheel uses docker container for
37+
# manylinux builds, so cache our vcpkg data on the
38+
# host filesystem (mounted to /host by default)
39+
- name: Point VCPKG_BINARY_SOURCES to host filesystem (Linux only)
40+
if: runner.os == 'Linux'
41+
run: |
42+
echo "VCPKG_BINARY_SOURCES=/host/${RUNNER_WORKSPACE}/b/vcpkg_cache" >> $GITHUB_ENV
43+
shell: bash
44+
45+
- name: run vcpkg
46+
uses: lukka/run-vcpkg@main
47+
id: run_vcpkg
48+
with:
49+
vcpkgDirectory: '${{ runner.workspace }}/b/vcpkg'
50+
vcpkgGitCommitId: '${{ matrix.vcpkgCommitId }}'
51+
# 'runVcpkgInstall=false' is especially important in the case of Linux -
52+
# we need the cibuildwheel Docker container to actually build/install
53+
# the dependencies, even if they are stored on the host filesystem
54+
# (exposed via the /host mount point) and cached by the host runner.
55+
runVcpkgInstall: false
56+
vcpkgJsonGlob: '**/build-scripts/vcpkg.json'
57+
58+
- name: List $RUNNER_WORKSPACE before build
59+
run: find $RUNNER_WORKSPACE
60+
shell: bash
61+
62+
- name: Normalize paths (Windows only)
63+
if: runner.os == 'Windows'
64+
run: |
65+
echo "UNIX_RUNNER_WORKSPACE=${RUNNER_WORKSPACE//\\//}" >> $GITHUB_ENV
66+
echo "UNIX_GITHUB_WORKSPACE=${GITHUB_WORKSPACE//\\//}" >> $GITHUB_ENV
67+
shell: bash
68+
69+
- name: Build wheels
70+
uses: pypa/cibuildwheel@v2.13.1
71+
env:
72+
CIBW_ENVIRONMENT_WINDOWS: >-
73+
SKBUILD_CONFIGURE_OPTIONS='
74+
-DCMAKE_TOOLCHAIN_FILE=${{ env.UNIX_RUNNER_WORKSPACE }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake
75+
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }}
76+
-DVCPKG_INSTALLED_DIR=${{ env.UNIX_RUNNER_WORKSPACE }}/b/vcpkg_installed
77+
-DVCPKG_MANIFEST_DIR=${{ env.UNIX_GITHUB_WORKSPACE }}/build-scripts
78+
-DUPSP_BUILD_TESTING=OFF -DUPSP_BUILD_APPLICATIONS=OFF -DUPSP_BUILD_PYBIND11=ON'
79+
CIBW_ENVIRONMENT_MACOS: >-
80+
SKBUILD_CONFIGURE_OPTIONS='
81+
-DCMAKE_TOOLCHAIN_FILE=${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake
82+
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }}
83+
-DVCPKG_INSTALLED_DIR=${{ runner.workspace }}/b/vcpkg_installed
84+
-DVCPKG_MANIFEST_DIR=${{ github.workspace }}/build-scripts
85+
-DUPSP_BUILD_TESTING=OFF -DUPSP_BUILD_APPLICATIONS=OFF -DUPSP_BUILD_PYBIND11=ON'
86+
CIBW_ENVIRONMENT_LINUX: >-
87+
SKBUILD_CONFIGURE_OPTIONS='
88+
-DCMAKE_TOOLCHAIN_FILE=/host/${{ runner.workspace }}/b/vcpkg/scripts/buildsystems/vcpkg.cmake
89+
-DVCPKG_TARGET_TRIPLET=${{ matrix.triplet }}
90+
-DVCPKG_INSTALLED_DIR=/host/${{ runner.workspace }}/b/vcpkg_installed
91+
-DVCPKG_MANIFEST_DIR=/host/${{ github.workspace }}/build-scripts
92+
-DUPSP_BUILD_TESTING=OFF -DUPSP_BUILD_APPLICATIONS=OFF -DUPSP_BUILD_PYBIND11=ON'
93+
CIBW_BEFORE_ALL_LINUX: "yum install -y perl-IPC-Cmd zip ninja-build"
94+
CIBW_BEFORE_BUILD_WINDOWS: "pip install cmake"
95+
CIBW_BUILD: "cp39-win_amd64 cp39-macosx_x86_64 cp39-manylinux_x86_64"
96+
CIBW_SKIP: "*-win32 *-manylinux_i686"
97+
CIBW_BUILD_VERBOSITY: 1
98+
with:
99+
package-dir: .
100+
output-dir: wheelhouse
101+
config-file: "{package}/pyproject.toml"
102+
103+
- uses: actions/upload-artifact@v3
104+
with:
105+
path: ./wheelhouse/*.whl
106+
107+
build_sdist:
108+
name: Build SDist
109+
runs-on: ubuntu-latest
110+
steps:
111+
- uses: actions/checkout@v3
112+
with:
113+
fetch-depth: 0 # for setuptools_scm
114+
115+
- name: Build SDist
116+
run: pipx run build --sdist
117+
118+
- uses: actions/upload-artifact@v3
119+
with:
120+
path: dist/*.tar.gz

CMakeLists.txt

Lines changed: 16 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ cmake_policy(SET CMP0074 NEW)
55
set(CMAKE_CXX_STANDARD 17)
66
set(CMAKE_CXX_STANDARD_REQUIRED ON)
77
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
8+
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
9+
10+
if (MSVC)
11+
# For MSVC to get things like "or", "and", ...
12+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /permissive-")
13+
endif()
814

915
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/Modules")
1016

@@ -21,170 +27,20 @@ if (DEFINED SKBUILD)
2127

2228
# TODO this is ugly but it works for now.
2329
#
24-
# When the project is built by scikit-build for deployment as a
25-
# Python package, libraries are dropped in the lib/ folder and there's
26-
# multiple consumers of those libraries that need to resolve them at runtime:
27-
#
28-
# - Executables, installed to bin/, need to look in $ORIGIN/../lib
29-
# - Python extension modules, installed to lib/pythonX/site-packages/upsp,
30-
# need to look in $ORIGIN/../../..
31-
#
32-
# Lastly, there's some build-tree-only artifacts (eg gtest unit tests),
33-
# those need to look in their own build directory ($ORIGIN).
34-
#
35-
# We could do this on a per-target basis but I'd rather just leave
36-
# the hack in one spot for now instead of being peppered all over
37-
# this build file.
38-
#
39-
# A "better/cleaner" example of this setup can be found here (although
40-
# I don't think it handles all the use cases I listed above, it's
41-
# a small sample project):
42-
#
43-
# https://github.com/scikit-build/scikit-build-sample-projects/blob/master/projects/hello-cmake-package/CMakeLists.txt#L92
30+
# Hard-code the appropriate library RPATHs, handling all possible "install" use cases.
31+
# - Installing libs for use in "standard" C/C++ <prefix>/lib install
32+
# - Installing libs for use in Python extensions
4433
#
34+
# Exact rpath syntax depends on target arch.
4535
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
46-
set(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/../lib:\$ORIGIN/../../../")
36+
if (APPLE)
37+
set(CMAKE_INSTALL_RPATH "@loader_path/;@loader_path/../../../")
38+
elseif (LINUX)
39+
set(CMAKE_INSTALL_RPATH "\$ORIGIN:\$ORIGIN/../lib:\$ORIGIN/../../../")
40+
endif()
4741
endif()
4842

49-
find_package(Eigen3 CONFIG REQUIRED)
50-
find_package(Boost REQUIRED)
51-
find_package(OpenCV CONFIG REQUIRED COMPONENTS core imgproc imgcodecs calib3d videoio tracking)
52-
find_package(OpenMP REQUIRED)
53-
find_package(MPI REQUIRED)
54-
find_package(Python3 COMPONENTS Interpreter Development)
55-
find_package(pybind11 REQUIRED)
56-
find_library(LIBRT rt)
57-
find_package(hdf5 CONFIG REQUIRED)
58-
find_package(IlmBase CONFIG REQUIRED)
59-
find_package(PythonExtensions)
60-
61-
include_directories(cpp/include)
62-
63-
pybind11_add_module(cine cpp/pybind11/cine.cpp)
64-
target_link_libraries(cine PRIVATE upsp_video)
65-
66-
pybind11_add_module(raycast cpp/pybind11/raycast.cpp)
67-
target_link_libraries(raycast PRIVATE upsp_kdtree)
68-
69-
add_library(
70-
upsp_video
71-
SHARED
72-
cpp/lib/PSPVideo.cpp
73-
cpp/lib/MrawReader.cpp
74-
cpp/lib/CineReader.cpp
75-
)
76-
target_link_libraries(upsp_video PRIVATE opencv_core)
77-
target_link_libraries(upsp_video PRIVATE Eigen3::Eigen)
78-
79-
add_library(
80-
upsp_utils
81-
SHARED
82-
cpp/utils/asyncIO.c
83-
cpp/utils/cv_extras.cpp
84-
cpp/utils/file_io.cpp
85-
cpp/utils/file_readers.cpp
86-
cpp/utils/file_writers.cpp
87-
cpp/utils/general_utils.cpp
88-
)
89-
target_link_libraries(upsp_utils PRIVATE opencv_core)
90-
target_link_libraries(upsp_utils PRIVATE ${LIBRT})
91-
target_link_libraries(upsp_utils PRIVATE upsp_video)
92-
target_link_libraries(upsp_utils PRIVATE Eigen3::Eigen)
93-
94-
add_library(
95-
upsp
96-
SHARED
97-
cpp/lib/cart3d.cpp
98-
cpp/lib/image_processing.cpp
99-
cpp/lib/logging.cpp
100-
cpp/lib/kulites.cpp
101-
cpp/lib/non_cv_upsp.cpp
102-
cpp/lib/patches.cpp
103-
cpp/lib/plot3d.cpp
104-
cpp/lib/projection.cpp
105-
cpp/lib/registration.cpp
106-
cpp/lib/upsp_inputs.cpp
107-
cpp/lib/CameraCal.cpp
108-
cpp/lib/PSPHDF5.cpp
109-
cpp/lib/P3DModel.cpp
110-
)
111-
target_link_libraries(upsp PUBLIC opencv_core opencv_imgproc opencv_tracking opencv_calib3d)
112-
target_link_libraries(upsp PRIVATE hdf5::hdf5_cpp-shared hdf5::hdf5_hl_cpp-shared)
113-
target_link_libraries(upsp PRIVATE Eigen3::Eigen)
114-
115-
add_library(
116-
upsp_kdtree
117-
SHARED
118-
cpp/utils/pspKdtree.c
119-
cpp/utils/pspRT.cpp
120-
cpp/utils/pspRTmem.cpp
121-
)
122-
target_link_libraries(upsp_kdtree IlmBase::Imath)
123-
124-
function(upsp_add_executable NAME)
125-
add_executable(${NAME} ${ARGN})
126-
target_link_libraries(${NAME} upsp)
127-
target_link_libraries(${NAME} upsp_video)
128-
target_link_libraries(${NAME} upsp_utils)
129-
target_link_libraries(${NAME} upsp_kdtree)
130-
target_link_libraries(${NAME} opencv_core)
131-
target_link_libraries(${NAME} opencv_videoio)
132-
target_link_libraries(${NAME} opencv_imgproc)
133-
target_link_libraries(${NAME} OpenMP::OpenMP_CXX)
134-
target_link_libraries(${NAME} hdf5::hdf5_cpp-shared hdf5::hdf5_hl_cpp-shared)
135-
target_link_libraries(${NAME} Eigen3::Eigen)
136-
endfunction()
137-
138-
upsp_add_executable(psp_process cpp/exec/psp_process.cpp)
139-
target_link_libraries(psp_process MPI::MPI_CXX)
140-
target_link_libraries(psp_process OpenMP::OpenMP_CXX)
141-
target_link_libraries(psp_process hdf5::hdf5_cpp-shared hdf5::hdf5_hl_cpp-shared)
142-
143-
add_executable(xyz_scalar_to_tbl cpp/exec/xyz_scalar_to_tbl.cpp)
144-
add_executable(xyz_scalar_to_tbl_delta cpp/exec/xyz_scalar_to_tbl_delta.cpp)
145-
146-
upsp_add_executable(upsp-extract-frames cpp/exec/upsp_extract_frames.cpp)
147-
148-
add_executable(add_field cpp/exec/add_field.cpp cpp/utils/asyncIO.c)
149-
target_link_libraries(add_field ${LIBRT})
150-
target_link_libraries(add_field hdf5::hdf5_cpp-shared hdf5::hdf5_hl_cpp-shared)
151-
152-
add_executable(upsp_matrix_transpose cpp/exec/upsp_matrix_transpose.cpp)
153-
target_link_libraries(upsp_matrix_transpose MPI::MPI_CXX)
154-
target_link_libraries(upsp_matrix_transpose OpenMP::OpenMP_CXX)
155-
156-
find_package(GTest CONFIG REQUIRED)
157-
upsp_add_executable(
158-
run_tests
159-
cpp/test/run_tests.cpp
160-
cpp/test/test_filtering.cpp
161-
cpp/test/test_general_utils.cpp
162-
cpp/test/test_grid_utils.cpp
163-
cpp/test/test_grids.cpp
164-
cpp/test/test_models.cpp
165-
cpp/test/test_mraw.cpp
166-
cpp/test/test_p3dmodel.cpp
167-
cpp/test/test_plot3d.cpp
168-
cpp/test/test_psphdf5.cpp
169-
cpp/test/test_trimodel.cpp
170-
)
171-
target_link_libraries(run_tests GTest::gtest GTest::gtest_main)
172-
target_link_libraries(run_tests OpenMP::OpenMP_CXX)
173-
target_link_libraries(run_tests hdf5::hdf5_cpp-shared hdf5::hdf5_hl_cpp-shared)
174-
175-
install(
176-
TARGETS
177-
add_field
178-
psp_process
179-
upsp
180-
upsp-extract-frames
181-
upsp_kdtree
182-
upsp_utils
183-
upsp_video
184-
xyz_scalar_to_tbl
185-
LIBRARY DESTINATION lib
186-
RUNTIME DESTINATION bin
187-
)
43+
add_subdirectory(cpp)
18844

18945
install(
19046
PROGRAMS
@@ -196,16 +52,3 @@ install(
19652
DESTINATION
19753
bin
19854
)
199-
200-
# TODO I think this works in a fairly brittle fashion right now.
201-
# It just so happens that the cmake_install_dir staging directory
202-
# created by scikit-build has a "python/upsp" folder mimicking the
203-
# source tree layout... so these extensions are just "dropped" into the
204-
# right spot. There's probably a more robust way to specify their
205-
# install location, probably some CMAKE_ variable I'm ignorant of.
206-
install(
207-
TARGETS
208-
cine
209-
raycast
210-
LIBRARY DESTINATION python/upsp
211-
)

build-scripts/vcpkg-setup-linux.sh

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#!/bin/bash
2+
3+
VCPKG_ROOT=/opt/vcpkg
4+
VCPKG_TRIPLET="x64-linux-dynamic"
5+
6+
echo "Settings up vcpkg in '$VCPKG_ROOT' ..."
7+
8+
yum install -y \
9+
perl-IPC-Cmd \
10+
zip
11+
12+
if [ ! -e "$VCPKG_ROOT" ]; then
13+
git clone \
14+
--depth 1 \
15+
--branch "2023.04.15" \
16+
https://github.com/Microsoft/vcpkg.git \
17+
$VCPKG_ROOT
18+
19+
pushd .
20+
cd $VCPKG_ROOT
21+
./bootstrap-vcpkg.sh -disableMetrics
22+
popd
23+
fi
24+
25+
pushd .
26+
cd $VCPKG_ROOT
27+
./vcpkg install --triplet=$VCPKG_TRIPLET \
28+
imath[core] \
29+
pybind11[core]
30+
31+
popd

build-scripts/vcpkg-setup-macos.sh

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#!/bin/bash
2+
3+
VCPKG_ROOT=$PWD/vcpkg
4+
VCPKG_TRIPLET="x64-osx-dynamic"
5+
6+
echo "Settings up vcpkg in '$VCPKG_ROOT' ..."
7+
8+
if [ ! -e "$VCPKG_ROOT" ]; then
9+
git clone \
10+
--depth 1 \
11+
--branch "2023.04.15" \
12+
https://github.com/Microsoft/vcpkg.git \
13+
$VCPKG_ROOT
14+
15+
pushd .
16+
cd $VCPKG_ROOT
17+
./bootstrap-vcpkg.sh -disableMetrics
18+
popd
19+
fi
20+
21+
pushd .
22+
cd $VCPKG_ROOT
23+
./vcpkg install --triplet=$VCPKG_TRIPLET \
24+
imath[core] \
25+
pybind11[core]
26+
27+
popd

build-scripts/vcpkg.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
3+
"dependencies": [
4+
"imath",
5+
"pybind11"
6+
]
7+
}

0 commit comments

Comments
 (0)