Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Python wheels in CI #1317

Merged
merged 37 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
37d9190
Use scikit-build-core to create a PyPI package (wheels + sdist)
JeanChristopheMorinPerso Apr 9, 2023
b9d3acf
Add new GH Actions workflow to build the wheels
JeanChristopheMorinPerso Apr 10, 2023
bcffe4e
Fix stdlib install
JeanChristopheMorinPerso Apr 10, 2023
bf105f1
Set MACOSX_DEPLOYMENT_TARGET to 10.13
JeanChristopheMorinPerso Apr 10, 2023
47396ff
Remove Python 3.11. We would need a newer Pybind11
JeanChristopheMorinPerso Apr 10, 2023
446e427
Reorganize workflow to build from sdist and disable MaterialXTest
JeanChristopheMorinPerso Apr 10, 2023
764315f
Fix pip install command
JeanChristopheMorinPerso Apr 10, 2023
057d018
Only run on 3.10 to speed up testing
JeanChristopheMorinPerso Apr 10, 2023
1980eae
Fix tests again...
JeanChristopheMorinPerso Apr 10, 2023
333d147
Re-enable all Python versions
JeanChristopheMorinPerso Apr 10, 2023
62d65b5
Minor spelling
jstone-lucasfilm Apr 10, 2023
54369db
Re-enable MATERIALX_BUILD_RENDER
JeanChristopheMorinPerso Apr 11, 2023
911f7c8
Add Python 3.11 to build matrix
jstone-lucasfilm Apr 25, 2023
d0b05a3
Add Python 3.11 to build matrix
jstone-lucasfilm Apr 25, 2023
f0b32fb
Update Python version range
jstone-lucasfilm Apr 25, 2023
8bc9f26
Simplify list of build exclusions
jstone-lucasfilm Apr 25, 2023
6b0dcfa
Minor workflow clarifications
jstone-lucasfilm Apr 26, 2023
669d7d4
Remove OCIO from Python build
jstone-lucasfilm Apr 26, 2023
3e71487
Minor naming updates
jstone-lucasfilm Apr 28, 2023
4252d6a
Update tests
JeanChristopheMorinPerso Jun 3, 2023
009c5ef
Get python package version from CMake
JeanChristopheMorinPerso Jun 3, 2023
aa175f4
Fix tests on Windows
JeanChristopheMorinPerso Jun 4, 2023
e0be564
Merge branch 'main' into python_packaging
jstone-lucasfilm Jun 13, 2023
aaab1cd
Merge branch 'main' into python_packaging
jstone-lucasfilm Jul 12, 2023
43c3fe9
Update script syntax
jstone-lucasfilm Jul 12, 2023
3e69d80
Use original concurrency rules in main
jstone-lucasfilm Jul 13, 2023
bb9804e
Merge branch 'main' into python_packaging
jstone-lucasfilm Jul 24, 2023
97ad91f
Merge branch 'main' into python_packaging
jstone-lucasfilm Aug 4, 2023
d1f7001
move mtx_skbuild_plugin.py into python folder
JeanChristopheMorinPerso Aug 4, 2023
6b4db09
Make sure there is no RPATH on Linux and macOS wheels
JeanChristopheMorinPerso Aug 5, 2023
a1c783e
Merge branch 'main' into python_packaging
jstone-lucasfilm Aug 17, 2023
ae2cae5
Remove TODO
jstone-lucasfilm Aug 18, 2023
6a8c7f9
Allow concurrent builds for now
jstone-lucasfilm Aug 18, 2023
5f98f72
Merge branch 'main' into python_packaging
jstone-lucasfilm Aug 18, 2023
2cade13
Minor spacing update
jstone-lucasfilm Aug 22, 2023
f775f6f
Remove forward slash for consistency
jstone-lucasfilm Aug 22, 2023
8f6a05f
Merge branch 'main' into python_packaging
jstone-lucasfilm Aug 22, 2023
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
132 changes: 132 additions & 0 deletions .github/workflows/python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: python

on:
push:
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:

concurrency:
cancel-in-progress: true
group: ${{ github.workflow }}-${{ github.ref }}

jobs:
# Generate the sdist first. We'll use it to create the wheels.
# https://packaging.python.org/en/latest/flow#the-source-distribution-sdist
sdist:
name: Generate Source Distribution
runs-on: ubuntu-latest
outputs:
sdist_filename: ${{ steps.generate.outputs.filename }}

steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v4
with:
python-version: 3.11

- name: Install Build Command
run: python -m pip install build

- name: Generate Sdist
id: generate
run: |
python -m build -s . --outdir dist
echo "filename=$(ls dist)" >> "$GITHUB_OUTPUT"

- name: Upload Sdist
uses: actions/upload-artifact@v3
with:
name: sdist
path: ./dist/*.tar.gz

# Create the wheels. It'll use the sdist to confirm that we can compile MaterialX from the sdist.
# https://packaging.python.org/en/latest/flow#the-built-distributions-wheels
wheels:
name: Generate Wheel
runs-on: ${{ matrix.os }}
needs: ['sdist']
strategy:
fail-fast: false
matrix:
python-version: ['37', '38', '39', '310', '311']
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']

steps:
- name: Download Sdist
uses: actions/download-artifact@v3
with:
name: sdist
path: sdist

- name: Build Wheel
# https://cibuildwheel.readthedocs.io/en/stable/
uses: pypa/[email protected]
with:
# Build from the sdist. We want to make sure it's valid and works as expected.
package-dir: ${{ github.workspace }}/sdist/${{ needs.sdist.outputs.sdist_filename }}
output-dir: wheels
env:
CIBW_BUILD: 'cp${{ matrix.python-version }}-*'
CIBW_SKIP: '*musllinux*'
CIBW_ARCHS: 'auto64'
# https://github.com/pypa/manylinux
# manylinux2014 is CentOS 7 based. Which means GCC 10 and glibc 2.17.
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
CIBW_BEFORE_ALL_LINUX: yum install -y libXt-devel
CIBW_BEFORE_ALL_MACOS: sudo xcode-select -switch /Applications/Xcode_13.4.app
CIBW_BUILD_VERBOSITY: 1
CIBW_ENVIRONMENT: CMAKE_BUILD_PARALLEL_LEVEL=2
# CIBW_BUILD_FRONTEND: build # https://github.com/pypa/build
MACOSX_DEPLOYMENT_TARGET: '10.15'

- name: Upload Wheel
uses: actions/upload-artifact@v3
with:
name: wheels
path: ./wheels/*.whl

test:
name: Test Wheel
needs: ['wheels']
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
os: ['ubuntu-latest', 'macos-latest', 'windows-latest']

steps:
- uses: actions/checkout@v3

- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}

- name: Download Wheels
uses: actions/download-artifact@v3
with:
name: wheels
path: wheels

- name: Install Wheel
run: python -m pip install MaterialX --find-links wheels --no-index

- name: Python Tests
shell: bash
run: |
set -e
python python/MaterialXTest/main.py
jstone-lucasfilm marked this conversation as resolved.
Show resolved Hide resolved
python python/MaterialXTest/genshader.py
python python/Scripts/mxformat.py ./resources/Materials/TestSuite/stdlib/upgrade --yes --upgrade
python python/Scripts/mxvalidate.py ./resources/Materials/Examples/StandardSurface/standard_surface_marble_solid.mtlx --stdlib --verbose
python python/Scripts/mxdoc.py --docType md ./libraries/pbrlib/pbrlib_defs.mtlx
python python/Scripts/mxdoc.py --docType html ./libraries/bxdf/standard_surface.mtlx
python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target glsl
python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target osl
python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target mdl
python python/Scripts/generateshader.py ./resources/Materials/Examples/StandardSurface --target msl
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
build
/dist
60 changes: 35 additions & 25 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ if (MATERIALX_BUILD_JS)
endif()
endif()

project(MaterialX)
project(MaterialX
VERSION ${MATERIALX_LIBRARY_VERSION}
)

option(MATERIALX_BUILD_PYTHON "Build the MaterialX Python package from C++ bindings. Requires Python 3.6 or greater." OFF)
option(MATERIALX_BUILD_VIEWER "Build the MaterialX Viewer." OFF)
Expand Down Expand Up @@ -80,6 +82,12 @@ set(MATERIALX_OSL_BINARY_OSLC "" CACHE FILEPATH "Full path to the OSL compiler b
set(MATERIALX_OSL_BINARY_TESTRENDER "" CACHE FILEPATH "Full path to the OSL test render binary.")
set(MATERIALX_OSL_INCLUDE_PATH "" CACHE PATH "Full path to OSL shader includes (e.g. 'stdosl.h').")

set(MATERIALX_PYTHON_FOLDER_NAME "python/MaterialX" CACHE INTERNAL "Folder name to user for installing the Python library.")

if(SKBUILD)
set(MATERIALX_PYTHON_FOLDER_NAME "MaterialX")
endif()

# Helpers for MDL validation
if (MATERIALX_BUILD_GEN_MDL)
set(MATERIALX_MDLC_EXECUTABLE "" CACHE FILEPATH "Full path to the mdlc binary.")
Expand Down Expand Up @@ -277,7 +285,7 @@ if(MATERIALX_BUILD_RENDER)
if(MATERIALX_BUILD_GRAPH_EDITOR)
add_subdirectory(source/MaterialXGraphEditor)
endif()
if(MATERIALX_INSTALL_RESOURCES)
if(MATERIALX_INSTALL_RESOURCES AND NOT SKBUILD)
add_subdirectory(resources)
endif()
endif()
Expand Down Expand Up @@ -312,26 +320,28 @@ if(${CMAKE_VERSION} VERSION_GREATER "3.6.2")
endif()

# Install root-level documents
install(FILES LICENSE CHANGELOG.md README.md THIRD-PARTY.md
DESTINATION .)

set(MATERIALX_GEN_CONFIG_PATH "${MATERIALX_INSTALL_LIB_PATH}/cmake/${CMAKE_PROJECT_NAME}")

include(CMakePackageConfigHelpers)
configure_package_config_file(cmake/modules/MaterialXConfig.cmake.in
${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake
INSTALL_DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
PATH_VARS CMAKE_INSTALL_PREFIX CMAKE_PROJECT_NAME)
write_basic_package_version_file(${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake
VERSION ${MATERIALX_LIBRARY_VERSION}
COMPATIBILITY AnyNewerVersion)

# Install the auto-generated CMake configuration files:

install(EXPORT MaterialX
DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
FILE ${CMAKE_PROJECT_NAME}Targets.cmake)

install(FILES "${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake"
"${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake"
DESTINATION "${MATERIALX_GEN_CONFIG_PATH}")
if(NOT SKBUILD)
install(FILES LICENSE CHANGELOG.md README.md THIRD-PARTY.md
DESTINATION .)

set(MATERIALX_GEN_CONFIG_PATH "${MATERIALX_INSTALL_LIB_PATH}/cmake/${CMAKE_PROJECT_NAME}")

include(CMakePackageConfigHelpers)
configure_package_config_file(cmake/modules/MaterialXConfig.cmake.in
${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake
INSTALL_DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
PATH_VARS CMAKE_INSTALL_PREFIX CMAKE_PROJECT_NAME)
write_basic_package_version_file(${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake
VERSION ${MATERIALX_LIBRARY_VERSION}
COMPATIBILITY AnyNewerVersion)

# Install the auto-generated CMake configuration files:

install(EXPORT MaterialX
DESTINATION "${MATERIALX_GEN_CONFIG_PATH}"
FILE ${CMAKE_PROJECT_NAME}Targets.cmake)

install(FILES "${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}ConfigVersion.cmake"
"${CMAKE_BINARY_DIR}/cmake/${CMAKE_PROJECT_NAME}Config.cmake"
DESTINATION "${MATERIALX_GEN_CONFIG_PATH}")
endif()
24 changes: 15 additions & 9 deletions libraries/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}" MESSAGE_NEVER
PATTERN "CMakeLists.txt" EXCLUDE
PATTERN "pbrlib_genosl_impl.*" EXCLUDE)

if (MATERIALX_OSL_LEGACY_CLOSURES)
set(PBRLIB_SUFFIX "legacy")
else()
set(PBRLIB_SUFFIX "mtlx")
endif()

install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
if(NOT SKBUILD)
install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}"
PATTERN "CMakeLists.txt" EXCLUDE
PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
DESTINATION "${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
endif()

set(MATERIALX_PYTHON_LIBRARIES_PATH "${MATERIALX_PYTHON_FOLDER_NAME}/${MATERIALX_INSTALL_STDLIB_PATH}")
if(SKBUILD)
set(MATERIALX_PYTHON_LIBRARIES_PATH "${SKBUILD_PLATLIB_DIR}/MaterialX/libraries")
endif()

install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/
DESTINATION "python/MaterialX/${MATERIALX_INSTALL_STDLIB_PATH}"
DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}"
PATTERN "CMakeLists.txt" EXCLUDE
PATTERN "pbrlib_genosl_impl.*" EXCLUDE)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/pbrlib/genosl/pbrlib_genosl_impl.${PBRLIB_SUFFIX}"
DESTINATION "python/MaterialX/${MATERIALX_INSTALL_STDLIB_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
DESTINATION "${MATERIALX_PYTHON_LIBRARIES_PATH}/pbrlib/genosl/" RENAME pbrlib_genosl_impl.mtlx)
90 changes: 90 additions & 0 deletions mtx_skbuild_plugin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
This is a custom scikit-build-core plugin that will
fetch the MaterialX version from the CMake project.
"""
JeanChristopheMorinPerso marked this conversation as resolved.
Show resolved Hide resolved
import os
import tempfile
import subprocess
from pathlib import Path
from typing import FrozenSet, Dict, Optional, Union, List

from scikit_build_core.file_api.query import stateless_query
from scikit_build_core.file_api.reply import load_reply_dir


def dynamic_metadata(
fields: FrozenSet[str],
settings: Optional[Dict[str, object]] = None,
) -> Dict[str, Union[str, Dict[str, Optional[str]]]]:
print("mtx_skbuild_plugin: Computing MaterialX version from CMake...")

if fields != {"version"}:
msg = "Only the 'version' field is supported"
raise ValueError(msg)

if settings:
msg = "No inline configuration is supported"
raise ValueError(msg)

current_dir = os.path.dirname(__file__)

with tempfile.TemporaryDirectory() as tmpdir:
# We will use CMake's file API to get the version
# instead of parsing the CMakeLists files.

# First generate the query folder so that CMake can generate replies.
reply_dir = stateless_query(Path(tmpdir))

# Run cmake (configure). CMake will generate a reply automatically.
try:
subprocess.run(
[
"cmake",
"-S",
current_dir,
"-B",
tmpdir,
"-DMATERIALX_BUILD_SHARED_LIBS=OFF",
"-DMATERIALX_BUILD_PYTHON=OFF",
"-DMATERIALX_TEST_RENDER=OFF",
"-DMATERIALX_BUILD_TESTS=OFF",
"-DMATERIALX_INSTALL_PYTHON=OFF",
"-DMATERIALX_BUILD_RENDER=OFF",
],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=True,
text=True,
)
except subprocess.CalledProcessError as exc:
print(exc.stdout)
raise RuntimeError(
"Failed to configure project to get the version"
) from exc

# Get the generated replies.
index = load_reply_dir(reply_dir)

# Get the version from the CMAKE_PROJECT_VERSION variable.
entries = [
entry
for entry in index.reply.cache_v2.entries
if entry.name == "CMAKE_PROJECT_VERSION"
]

if not entries:
raise ValueError("Could not find MaterialX version from CMake project")

if len(entries) > 1:
raise ValueError("More than one entry for CMAKE_PROJECT_VERSION found...")

version = entries[0].value
print("mtx_skbuild_plugin: Computed version: {0}".format(version))

return {"version": version}


def get_requires_for_dynamic_metadata(
_settings: Optional[Dict[str, object]] = None,
) -> List[str]:
return ["cmake"]
Loading