Skip to content

Commit 47d758a

Browse files
authored
Add command line apps to Python wheel (#1802)
* Add command line apps and remove tests on Python wheel Signed-off-by: Rémi Achard <[email protected]> * Fix warnings on Clang 14 Signed-off-by: Rémi Achard <[email protected]> * Python wheel using dynamic linking Signed-off-by: Rémi Achard <[email protected]> * Fix DLL directory Signed-off-by: Rémi Achard <[email protected]> * Check path exists Signed-off-by: Rémi Achard <[email protected]> * Fix DLL lookup on Windows Signed-off-by: Rémi Achard <[email protected]> * Fix linux / mac wheels Signed-off-by: Rémi Achard <[email protected]> * Fix symlinks and make doc optional Signed-off-by: Rémi Achard <[email protected]> --------- Signed-off-by: Rémi Achard <[email protected]>
1 parent 929d536 commit 47d758a

File tree

27 files changed

+209
-49
lines changed

27 files changed

+209
-49
lines changed

.github/workflows/wheel_workflow.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ jobs:
128128
platforms: all
129129

130130
- name: Build wheels
131-
uses: pypa/cibuildwheel@v2.12.0
131+
uses: pypa/cibuildwheel@v2.13.1
132132
env:
133133
CIBW_BUILD: ${{ matrix.python }}
134134
CIBW_ARCHS: ${{ matrix.arch }}
@@ -194,7 +194,7 @@ jobs:
194194
python-version: '3.8'
195195

196196
- name: Build wheels
197-
uses: pypa/cibuildwheel@v2.12.0
197+
uses: pypa/cibuildwheel@v2.13.1
198198
env:
199199
CIBW_BUILD: ${{ matrix.python }}
200200
CIBW_ARCHS: ${{ matrix.arch }}
@@ -245,7 +245,7 @@ jobs:
245245
python-version: '3.8'
246246

247247
- name: Build wheels
248-
uses: pypa/cibuildwheel@v2.12.0
248+
uses: pypa/cibuildwheel@v2.13.1
249249
env:
250250
CIBW_BUILD: ${{ matrix.python }}
251251
CIBW_ARCHS: ${{ matrix.arch }}

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,9 @@ endif()
159159

160160
###############################################################################
161161
# Other preferences
162+
162163
option(OCIO_VERBOSE "Display more information when searching or installing dependencies" OFF)
164+
option(OCIO_USE_SOVERSION "Enable versioning in OCIO shared library name" ON)
163165

164166
###############################################################################
165167
# Warnings / debugging settings
@@ -190,6 +192,7 @@ if ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "(AMD64|IA64|EM64T|X86|x86_64|i386|i686)
190192
set(OCIO_ARCH_X86 1)
191193
endif()
192194

195+
193196
###############################################################################
194197
# GPU configuration
195198
message(STATUS "")

pyproject.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,11 @@ build-backend = "setuptools.build_meta"
1717
[tool.cibuildwheel]
1818
build-verbosity = "1"
1919

20-
test-command = "python -m PyOpenColorIO.tests.OpenColorIOTestSuite"
2120
test-requires = ["numpy"]
21+
test-command = [
22+
"python {project}/tests/python/OpenColorIOTestSuite.py",
23+
"ociocheck"
24+
]
2225

2326
manylinux-x86_64-image = "manylinux2014"
2427
manylinux-i686-image = "manylinux2014"

setup.py

Lines changed: 84 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
import os
88
import re
9-
import shutil
109
import subprocess
1110
import sys
1211
import tempfile
@@ -16,27 +15,49 @@
1615

1716

1817
# Extract the project version from CMake generated ABI header.
19-
# NOTE: When droping support for Python2 we can use
20-
# tempfile.TemporaryDirectory() context manager instead of try...finally.
2118
def get_version():
2219
VERSION_REGEX = re.compile(
2320
r"^\s*#\s*define\s+OCIO_VERSION_FULL_STR\s+\"(.*)\"\s*$", re.MULTILINE)
2421

2522
here = os.path.abspath(os.path.dirname(__file__))
26-
dirpath = tempfile.mkdtemp()
27-
28-
try:
29-
stdout = subprocess.check_output(["cmake", here], cwd=dirpath)
30-
path = os.path.join(dirpath, "include", "OpenColorIO", "OpenColorABI.h")
31-
with open(path) as f:
32-
match = VERSION_REGEX.search(f.read())
33-
return match.group(1)
34-
except Exception as e:
35-
raise RuntimeError(
36-
"Unable to find OpenColorIO version: {}".format(str(e))
37-
)
38-
finally:
39-
shutil.rmtree(dirpath)
23+
24+
with tempfile.TemporaryDirectory() as tmpdir:
25+
try:
26+
subprocess.check_call(["cmake", here], cwd=tmpdir)
27+
path = os.path.join(tmpdir, "include", "OpenColorIO", "OpenColorABI.h")
28+
with open(path) as f:
29+
match = VERSION_REGEX.search(f.read())
30+
return match.group(1)
31+
except Exception as e:
32+
raise RuntimeError(
33+
"Unable to find OpenColorIO version: {}".format(str(e))
34+
)
35+
36+
37+
# Call CMake find_package from a dummy script and return whether the package
38+
# has been found or not.
39+
def cmake_find_package(package_name):
40+
with tempfile.TemporaryDirectory() as tmpdir:
41+
try:
42+
cmakelist_path = os.path.join(tmpdir, "CMakeLists.txt")
43+
with open(cmakelist_path, "w") as f:
44+
f.write("""
45+
cmake_minimum_required(VERSION 3.13)
46+
project(test LANGUAGES CXX)
47+
48+
find_package({} REQUIRED)
49+
""".format(package_name)
50+
)
51+
52+
subprocess.check_call(
53+
["cmake", tmpdir],
54+
cwd=tmpdir,
55+
stdout=subprocess.DEVNULL,
56+
stderr=subprocess.DEVNULL
57+
)
58+
return True
59+
except Exception as e:
60+
return False
4061

4162

4263
# Convert distutils Windows platform specifiers to CMake -A arguments
@@ -59,6 +80,7 @@ def __init__(self, name, sourcedir=""):
5980
class CMakeBuild(build_ext):
6081
def build_extension(self, ext):
6182
extdir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name)))
83+
bindir = os.path.join(extdir, "bin")
6284

6385
# required for auto-detection & inclusion of auxiliary "native" libs
6486
if not extdir.endswith(os.path.sep):
@@ -73,12 +95,13 @@ def build_extension(self, ext):
7395

7496
cmake_args = [
7597
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY={}".format(extdir),
98+
"-DCMAKE_RUNTIME_OUTPUT_DIRECTORY={}".format(bindir),
7699
"-DPython_EXECUTABLE={}".format(sys.executable),
77100
# Not used on MSVC, but no harm
78101
"-DCMAKE_BUILD_TYPE={}".format(cfg),
79-
"-DBUILD_SHARED_LIBS=OFF",
80-
"-DOCIO_BUILD_DOCS=ON",
81-
"-DOCIO_BUILD_APPS=OFF",
102+
"-DBUILD_SHARED_LIBS=ON",
103+
"-DOCIO_USE_SOVERSION=OFF",
104+
"-DOCIO_BUILD_APPS=ON",
82105
"-DOCIO_BUILD_TESTS=OFF",
83106
"-DOCIO_BUILD_GPU_TESTS=OFF",
84107
# Make sure we build everything for the requested architecture(s)
@@ -121,7 +144,8 @@ def build_extension(self, ext):
121144
# Multi-config generators have a different way to specify configs
122145
if not single_config:
123146
cmake_args += [
124-
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir)
147+
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), extdir),
148+
"-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_{}={}".format(cfg.upper(), bindir),
125149
]
126150
build_args += ["--config", cfg]
127151

@@ -131,6 +155,19 @@ def build_extension(self, ext):
131155
if archs:
132156
cmake_args += ["-DCMAKE_OSX_ARCHITECTURES={}".format(";".join(archs))]
133157

158+
# When building the wheel, the install step is not executed so we need
159+
# to have the correct RPATH directly from the build tree output.
160+
cmake_args += ["-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON"]
161+
if sys.platform.startswith("linux"):
162+
cmake_args += ["-DCMAKE_INSTALL_RPATH={}".format("$ORIGIN;$ORIGIN/..")]
163+
if sys.platform.startswith("darwin"):
164+
cmake_args += ["-DCMAKE_INSTALL_RPATH={}".format("@loader_path;@loader_path/..")]
165+
166+
# Documentation is used for Python docstrings but we allow to build
167+
# the wheel without docs to remove a hard dependency on doxygen.
168+
if cmake_find_package("Doxygen"):
169+
cmake_args += ["-DOCIO_BUILD_DOCS=ON"]
170+
134171
# Set CMAKE_BUILD_PARALLEL_LEVEL to control the parallel build level
135172
# across all generators.
136173
if "CMAKE_BUILD_PARALLEL_LEVEL" not in os.environ:
@@ -156,11 +193,33 @@ def build_extension(self, ext):
156193
version=get_version(),
157194
package_dir={
158195
'PyOpenColorIO': 'src/bindings/python/package',
159-
'PyOpenColorIO.tests': 'tests/python',
160-
'PyOpenColorIO.data': 'tests/data',
196+
'PyOpenColorIO.bin.pyocioamf': 'src/apps/pyocioamf',
197+
'PyOpenColorIO.bin.pyociodisplay': 'src/apps/pyociodisplay',
161198
},
162-
packages=['PyOpenColorIO', 'PyOpenColorIO.tests', 'PyOpenColorIO.data'],
199+
packages=[
200+
'PyOpenColorIO',
201+
'PyOpenColorIO.bin.pyocioamf',
202+
'PyOpenColorIO.bin.pyociodisplay',
203+
],
163204
ext_modules=[CMakeExtension("PyOpenColorIO.PyOpenColorIO")],
164205
cmdclass={"build_ext": CMakeBuild},
165-
include_package_data=True
206+
include_package_data=True,
207+
entry_points={
208+
'console_scripts': [
209+
# Native applications
210+
'ocioarchive=PyOpenColorIO.command_line:main',
211+
'ociobakelut=PyOpenColorIO.command_line:main',
212+
'ociocheck=PyOpenColorIO.command_line:main',
213+
'ociochecklut=PyOpenColorIO.command_line:main',
214+
'ocioconvert=PyOpenColorIO.command_line:main',
215+
'ociodisplay=PyOpenColorIO.command_line:main',
216+
'ociolutimage=PyOpenColorIO.command_line:main',
217+
'ociomakeclf=PyOpenColorIO.command_line:main',
218+
'ocioperf=PyOpenColorIO.command_line:main',
219+
'ociowrite=PyOpenColorIO.command_line:main',
220+
# Python applications
221+
'pyocioamf=PyOpenColorIO.bin.pyocioamf.pyocioamf:main',
222+
'pyociodisplay=PyOpenColorIO.bin.pyociodisplay.pyociodisplay:main',
223+
]
224+
},
166225
)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# SPDX-License-Identifier: BSD-3-Clause
2+
# Copyright Contributors to the OpenColorIO Project.
3+
4+
# This function is based on Pybind11's pybind11_strip.
5+
6+
macro(ocio_strip_binary target_name)
7+
string(TOUPPER "${CMAKE_BUILD_TYPE}" _uppercase_CMAKE_BUILD_TYPE)
8+
if(NOT MSVC AND NOT "${_uppercase_CMAKE_BUILD_TYPE}" MATCHES DEBUG|RELWITHDEBINFO)
9+
if(CMAKE_STRIP)
10+
if(APPLE)
11+
set(_strip_opt -x)
12+
endif()
13+
14+
add_custom_command(
15+
TARGET ${target_name}
16+
POST_BUILD
17+
COMMAND ${CMAKE_STRIP} ${_strip_opt} $<TARGET_FILE:${target_name}>
18+
)
19+
unset(_strip_opt)
20+
endif()
21+
endif()
22+
unset(_uppercase_CMAKE_BUILD_TYPE)
23+
endmacro()

share/cmake/utils/CompilerFlags.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ endif()
120120
###############################################################################
121121
# Define RPATH.
122122

123-
if (UNIX AND NOT CMAKE_SKIP_RPATH)
123+
if (UNIX AND NOT CMAKE_SKIP_RPATH AND NOT CMAKE_INSTALL_RPATH)
124124
# With the 'usual' install path structure in mind, search from the bin directory
125125
# (i.e. a binary loading a dynamic library) and then from the current directory
126126
# (i.e. dynamic library loading another dynamic library).

src/OpenColorIO/CMakeLists.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,12 +411,17 @@ elseif(APPLE)
411411
endif()
412412
endif()
413413

414+
if (OCIO_USE_SOVERSION)
415+
set_target_properties(OpenColorIO PROPERTIES
416+
VERSION ${OpenColorIO_VERSION}
417+
SOVERSION ${SOVERSION}
418+
)
419+
endif()
420+
414421
set_target_properties(OpenColorIO PROPERTIES
415422
OUTPUT_NAME ${PROJECT_NAME}${OCIO_LIBNAME_SUFFIX}
416423
COMPILE_OPTIONS "${PLATFORM_COMPILE_OPTIONS}"
417424
LINK_OPTIONS "${CUSTOM_LINK_FLAGS}"
418-
VERSION ${OpenColorIO_VERSION}
419-
SOVERSION ${SOVERSION}
420425
PUBLIC_HEADER "${INSTALL_HEADERS}"
421426
)
422427

src/OpenColorIO/ops/lut3d/Lut3DOpCPU.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,7 +1664,6 @@ void InvLut3DRenderer::apply(const void * inImg, void * outImg, long numPixels)
16641664
// For now, if no result is found, return 0.
16651665
float result[3] = { 0.f, 0.f, 0.f };
16661666

1667-
unsigned long cnt = 0;
16681667
long level = 0;
16691668
while (level >= 0)
16701669
{
@@ -1680,7 +1679,6 @@ void InvLut3DRenderer::apply(const void * inImg, void * outImg, long numPixels)
16801679
B <= levels[level].maxVals[node * chans + 2];
16811680
currentChild[level]++;
16821681
currentChildInd[level]++;
1683-
cnt++;
16841682

16851683
if (inRange)
16861684
{
@@ -1757,4 +1755,3 @@ ConstOpCPURcPtr GetLut3DRenderer(ConstLut3DOpDataRcPtr & lut)
17571755
}
17581756

17591757
} // namespace OCIO_NAMESPACE
1760-

src/apps/ocioarchive/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ target_link_libraries(ocioarchive
2424
MINIZIP::minizip-ng
2525
)
2626

27+
include(StripUtils)
28+
ocio_strip_binary(ocioarchive)
29+
2730
install(TARGETS ocioarchive
2831
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
2932
)

src/apps/ociobakelut/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ target_link_libraries(ociobakelut
3333
OpenColorIO
3434
)
3535

36+
include(StripUtils)
37+
ocio_strip_binary(ociobakelut)
38+
3639
install(TARGETS ociobakelut
3740
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
3841
)

0 commit comments

Comments
 (0)