Skip to content

Commit 77339f6

Browse files
committed
[Build] Add hybrid python generation to cmake.
[OpenAssetIO#49] Adds the ability to optionally and additionally generate the python package when running under the cmake build system. This is intended to enable hybrid hosts/managers to get both of their required libraries out without needing to call out/synchronize between multiple build systems (cmake & pip) Signed-off-by: Elliot Morris <[email protected]>
1 parent 43f62ab commit 77339f6

File tree

4 files changed

+134
-8
lines changed

4 files changed

+134
-8
lines changed

.github/workflows/test.yml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
run: python -m pytest -v
4242

4343
test-cpp:
44-
name: Test-Cpp
44+
name: Test Cpp
4545
runs-on: ubuntu-latest
4646
needs: build-openassetio
4747
container:
@@ -68,3 +68,34 @@ jobs:
6868

6969
- name: Test
7070
run: ctest -VV --test-dir build/tests/cpp --parallel 2
71+
72+
test-python-from-cmake:
73+
# To support hybrid C++ applications, the python package may also be
74+
# generated using the CMake packaging, in addition and simultaneously
75+
# to the C++ package. This tests that.
76+
name: "Test Python From CMake"
77+
runs-on: ubuntu-latest
78+
container:
79+
image: aswf/ci-vfxall:2022-clang14.3
80+
steps:
81+
- uses: actions/checkout@v3
82+
83+
- name: Install Traitgen
84+
run: python -m pip install openassetio-traitgen==1.0.0a6
85+
86+
- name: Configure CMake build
87+
run: >
88+
cmake -S . -B build -G Ninja
89+
-DOPENASSETIO_MEDIACREATION_GENERATE_PYTHON=ON
90+
-DOPENASSETIO_MEDIACREATION_PYTHON_SITEDIR="hybridpython"
91+
92+
- name: Install package
93+
run: cmake --install build
94+
95+
- name: Install OpenAssetIO
96+
run: python -m pip install openassetio>=1.0.0a6
97+
98+
- name: Test
99+
run: |
100+
python -m pip install -r tests/python/requirements.txt
101+
PYTHONPATH=$(pwd)/build/dist/hybridpython python -m pytest -v

CMakeLists.txt

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,18 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake)
1414
#-----------------------------------------------------------------------
1515
# Options
1616
option(OPENASSETIO_MEDIACREATION_ENABLE_TEST "Run test on mediacreation traits" OFF)
17+
option(OPENASSETIO_MEDIACREATION_GENERATE_PYTHON "Aditionally generate python library" OFF)
18+
if (OPENASSETIO_MEDIACREATION_GENERATE_PYTHON)
19+
# By default we'll compute the correct site-packages directory
20+
# structure, but allow overriding.
21+
set(OPENASSETIO_MEDIACREATION_PYTHON_SITEDIR
22+
""
23+
CACHE STRING
24+
"Override default Python module install directory, relative to CMAKE_INSTALL_PREFIX")
25+
endif ()
26+
1727
message(STATUS "Test enabled = ${OPENASSETIO_MEDIACREATION_ENABLE_TEST}")
28+
message(STATUS "Generate python library = ${OPENASSETIO_MEDIACREATION_GENERATE_PYTHON}")
1829

1930
# ABI wrangling only needed for test
2031
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND
@@ -61,21 +72,40 @@ message("Generating Traits with openassetio-traitgen")
6172
# This means if the source traits file is changed, configure will rerun.
6273
configure_file(${CMAKE_CURRENT_LIST_DIR}/traits.yml ${PROJECT_BINARY_DIR}/traits.yml)
6374
execute_process(COMMAND openassetio-traitgen ${PROJECT_BINARY_DIR}/traits.yml
64-
-o ${PROJECT_BINARY_DIR} -g cpp
65-
COMMAND_ERROR_IS_FATAL ANY
66-
COMMAND_ECHO STDERR)
75+
-o ${PROJECT_BINARY_DIR}/cpp -g cpp
76+
COMMAND_ERROR_IS_FATAL ANY
77+
COMMAND_ECHO STDERR)
78+
79+
if (OPENASSETIO_MEDIACREATION_GENERATE_PYTHON)
80+
# Generate the python package by running traitgen.
81+
# By running traitgen during the cmake step, using the traitgen that
82+
# is available to the environment, just as the C++ generation does,
83+
# we guarentee that the versions of traitgen used between c++ and
84+
# python packages are identical. This isn't a guarentee when using
85+
# the `pip install .` method of creating a python package, due to
86+
# pip having a seperate dependency resolution method.
87+
#
88+
# At the time of writing, this produces the same artifact as doing
89+
# `pip install .` (and invoking setup.py), but that's not a
90+
# guarentee going forward, as additional elements of the python
91+
# package may be added to mediacreation.
92+
execute_process(COMMAND openassetio-traitgen ${PROJECT_BINARY_DIR}/traits.yml
93+
-o ${PROJECT_BINARY_DIR}/python -g python
94+
COMMAND_ERROR_IS_FATAL ANY
95+
COMMAND_ECHO STDERR)
96+
endif()
6797

6898
add_library(openassetio-mediacreation INTERFACE)
6999
# add alias so the project can be used with add_subdirectory
70100
add_library(OpenAssetIO-MediaCreation::openassetio-mediacreation ALIAS openassetio-mediacreation)
71101

72102
include(GNUInstallDirs)
73103

74-
# traitgen generates to _public_header_source_root location by default.
75-
set(_public_header_source_root "${PROJECT_BINARY_DIR}/openassetio_mediacreation/include")
104+
# traitgen generates to _public_header_source_root/cpp location by default.
105+
set(_public_header_source_root "${PROJECT_BINARY_DIR}/cpp/openassetio_mediacreation/include")
76106
set(_config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
77-
set(_project_config_file "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake")
78-
set(_version_config_file "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
107+
set(_project_config_file "${PROJECT_BINARY_DIR}/cpp/${PROJECT_NAME}Config.cmake")
108+
set(_version_config_file "${PROJECT_BINARY_DIR}/cpp/${PROJECT_NAME}ConfigVersion.cmake")
79109
set(_traitgen_data_dir "${CMAKE_INSTALL_DATADIR}/openassetio-traitgen")
80110

81111
#-----------------------------------------------------------------------
@@ -112,6 +142,18 @@ install(
112142
FILE ${PROJECT_NAME}Targets.cmake
113143
)
114144

145+
#-----------------------------------------------------------------------
146+
# Optionally install python library
147+
if (OPENASSETIO_MEDIACREATION_GENERATE_PYTHON)
148+
include(ThirdParty)
149+
150+
install(
151+
DIRECTORY ${PROJECT_BINARY_DIR}/python/openassetio_mediacreation
152+
DESTINATION "${OPENASSETIO_MEDIACREATION_PYTHON_SITEDIR}"
153+
FILES_MATCHING PATTERN "*.py"
154+
)
155+
endif()
156+
115157
#-----------------------------------------------------------------------
116158
# Copy CMake Files
117159
install(

RELEASE_NOTES.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
Release Notes
22
=============
33

4+
v1.0.0-alpha.x
5+
--------------
6+
### New Features
7+
8+
- Added ability to generate python package whilst installing via cmake
9+
build system.
10+
Added cmake variables `OPENASSETIO_MEDIACREATION_GENERATE_PYTHON` and
11+
`OPENASSETIO_MEDIACREATION_PYTHON_SITEDIR` to support this.
12+
413
v1.0.0-alpha.6
514
--------------
615

cmake/ThirdParty.cmake

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#-----------------------------------------------------------------------
2+
# Python
3+
4+
if (OPENASSETIO_MEDIACREATION_GENERATE_PYTHON)
5+
#-------------------------------------------------------------------
6+
# Locate packages
7+
8+
# Locate the Python package.
9+
find_package(Python REQUIRED COMPONENTS Interpreter)
10+
11+
# Debug log some outputs expected from the built-in FindPython.
12+
message(TRACE "Python_EXECUTABLE = ${Python_EXECUTABLE}")
13+
message(TRACE "Python_INTERPRETER_ID = ${Python_INTERPRETER_ID}")
14+
message(TRACE "Python_STDLIB = ${Python_STDLIB}")
15+
message(TRACE "Python_STDARCH = ${Python_STDARCH}")
16+
message(TRACE "Python_SITELIB = ${Python_SITELIB}")
17+
message(TRACE "Python_SITEARCH = ${Python_SITEARCH}")
18+
message(TRACE "Python_SOABI = ${Python_SOABI}")
19+
message(TRACE "Python_INCLUDE_DIRS = ${Python_INCLUDE_DIRS}")
20+
message(TRACE "Python_LINK_OPTIONS = ${Python_LINK_OPTIONS}")
21+
message(TRACE "Python_LIBRARIES = ${Python_LIBRARIES}")
22+
message(TRACE "Python_LIBRARY_DIRS = ${Python_LIBRARY_DIRS}")
23+
message(TRACE "Python_RUNTIME_LIBRARY_DIRS = ${Python_RUNTIME_LIBRARY_DIRS}")
24+
message(TRACE "Python_VERSION = ${Python_VERSION}")
25+
message(TRACE "Python_VERSION_MAJOR = ${Python_VERSION_MAJOR}")
26+
message(TRACE "Python_VERSION_MINOR = ${Python_VERSION_MINOR}")
27+
message(TRACE "Python_VERSION_PATCH = ${Python_VERSION_PATCH}")
28+
29+
if (OPENASSETIO_MEDIACREATION_PYTHON_SITEDIR STREQUAL "")
30+
# Make a naive assumption about a suitable structure under our
31+
# install-dir. See:
32+
# https://discuss.python.org/t/understanding-site-packages-directories/12959
33+
# We had issues using 'cleverness' to work out the path relative
34+
# to Python_EXECUTABLE and Python_SITEARCH when symlinks or
35+
# varying installation structures were used (eg GitHub Actions
36+
# runners).
37+
if (WIN32)
38+
set(OPENASSETIO_MEDIACREATION_PYTHON_SITEDIR "Lib/site-packages")
39+
else ()
40+
set(OPENASSETIO_MEDIACREATION_PYTHON_SITEDIR
41+
"lib/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages")
42+
endif ()
43+
endif ()
44+
endif()

0 commit comments

Comments
 (0)