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 conda_recipes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ building new packages for either Linux or Windows into it on AWS Deadline Cloud.

## Recipe index

This table covers all 50 immediate user-selectable recipe directories in `conda_recipes/`.
This table covers all 51 immediate user-selectable recipe directories in `conda_recipes/`.

| Sample | What it demonstrates | Start here when |
|---|---|---|
Expand Down Expand Up @@ -51,6 +51,7 @@ This table covers all 50 immediate user-selectable recipe directories in `conda_
| [KeyShot 2025](keyshot-2025/) | Packaging KeyShot 2025.2 for Windows | Your jobs render with KeyShot |
| [Maya 2025](maya-2025/) | Packaging Maya and configuring module/plugin search paths | Your jobs require Maya 2025 |
| [Maya 2026](maya-2026/) | Packaging Maya with Plugin Sync activation | Your jobs require Maya 2026 or frequently updated plugins |
| [Maya 2027](maya-2027/) | Packaging Maya with Plugin Sync activation | Your jobs require Maya 2027 |
| [Bifrost for Maya 2026](maya-bifrost-2026/) | Packaging Autodesk Bifrost for Maya | Maya 2026 jobs use Bifrost graphs or simulations |
| [Arnold for Maya 2025](maya-mtoa-2025/) | Packaging MtoA against the Maya 2025 package | Maya 2025 jobs render with Arnold |
| [Arnold for Maya 2026](maya-mtoa-2026/) | Packaging MtoA against the Maya 2026 package | Maya 2026 jobs render with Arnold |
Expand Down
19 changes: 19 additions & 0 deletions conda_recipes/maya-2027/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Maya 2027 conda build recipe

## Instructions for Maya plugin packages

This Maya conda build recipe configures the `MAYA_MODULE_PATH` environment variable
to include the paths to search for plugin `.mod` files. When creating a plugin
package, place its `.mod` file in one of these so that Maya loads the plugin at startup.

* `$PREFIX/usr/autodesk/maya$MAYA_VERSION/modules`
* `$PREFIX/usr/autodesk/modules/maya/$MAYA_VERSION`
* `$PREFIX/usr/autodesk/modules/maya`

## Download the archive file for Linux

Download the Autodesk_Maya_2027_Linux_64bit.tgz full download file from Autodesk, and
place it in the `conda_recipes/archive_files` directory in your git clone of the
[deadline-cloud-samples](https://github.com/aws-deadline/deadline-cloud-samples) repository for
submitting package build jobs.

11 changes: 11 additions & 0 deletions conda_recipes/maya-2027/deadline-cloud.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
condaPlatforms:
- platform: linux-64
defaultSubmit: true
sourceArchiveFilename:
- Autodesk_Maya_2027_Linux_64bit.tgz
sourceDownloadInstructions: 'Download the Autodesk_Maya_2027_Linux_64bit.tgz full download file from Autodesk.'
buildTool: rattler-build
jobParameters:
# conda-forge is used to get patchelf on Linux
- name: CondaChannels
value: conda-forge
145 changes: 145 additions & 0 deletions conda_recipes/maya-2027/recipe/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/bin/sh

# Echo all the commands so debugging from log output is simpler
set -x
# Fail the script if any commands it runs fail
set -euo pipefail

# The version without the update number
MAYA_VERSION=${PKG_VERSION%.*}
# The location within $PREFIX where the RPM file extracts Maya
AUTODESK_ROOT="usr/autodesk"
MAYA_ROOT="$AUTODESK_ROOT/maya$MAYA_VERSION"
INSTALL_DIR="$PREFIX/$MAYA_ROOT"

cd $PREFIX

# Extract the Maya RPM
rpm2cpio "$SRC_DIR/installer/Packages"/Maya${MAYA_VERSION}_64-$PKG_VERSION-*.x86_64.rpm | cpio -idm

# Remove examples, they're not needed on the farm
rm -r "$MAYA_ROOT"/Examples

# Maya needs this symlink that rpm2cpio did not create
ln -r -s "$INSTALL_DIR/bin/maya$MAYA_VERSION" "$INSTALL_DIR/bin/maya"

# Install the Autodesk Desktop Analytics (ADP) SDK.
#
# Maya 2027 dlopen()s AdpSDKCore.so during startup and exits with status 255, printing
# nothing, if it is missing. Earlier Maya releases tolerated its absence. The SDK is not
# part of the Maya RPM; the installer ships it as a separate package that Autodesk's own
# setup program installs. $MAYA_LOCATION/lib is one of the paths Maya probes for it.
#
# The MAYA_DISABLE_ADP / MAYA_DISABLE_CIP / MAYA_DISABLE_CER environment variables do NOT
# avoid this: they suppress reporting after the library loads, so the library must be
# present regardless. They are still set in env_vars.d below so nothing is transmitted.
unzip -q -o "$SRC_DIR/installer/Packages/AdpSdk/adp-desktop-sdk.zip" -d "$INSTALL_DIR/lib"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracting the ADP SDK zip directly on top of Maya's own lib/ with -o (force overwrite) and -q (quiet) means any name collision between the SDK payload and a library the Maya RPM shipped in that directory is resolved silently in the SDK's favour, with nothing in the build log to show it happened. That is a hard failure to diagnose later — Maya starts (or doesn't) with a mix of libraries no one intended.

The same line also has no post-condition check. If a future SDK drop nests its payload (e.g. lib/AdpSDKCore.so or linux/AdpSDKCore.so inside the zip) rather than storing the .so files at the archive root, unzip still succeeds, so set -e won't catch it — the libraries just land somewhere Maya doesn't probe. Per the comment directly above, the runtime symptom is Maya exiting 255 printing nothing, which is exactly the failure this block exists to prevent, and it would only surface on the farm rather than in the build.

Suggest extracting to a scratch directory, asserting the expected library is present, and then copying it into place explicitly, so both problems fail the build instead of the render:

_adp_tmp="$SRC_DIR/adp-sdk"
mkdir -p "$_adp_tmp"
unzip -q -o "$SRC_DIR/installer/Packages/AdpSdk/adp-desktop-sdk.zip" -d "$_adp_tmp"
# Fail the build here rather than at render time with Maya's silent exit 255.
test -n "$(find "$_adp_tmp" -name 'AdpSDKCore.so' -print -quit)"
find "$_adp_tmp" -name '*.so' -exec cp -n {} "$INSTALL_DIR/lib/" \;

Using cp -n also surfaces, rather than hides, the collision case.


# Give the ADP libraries an rpath so they can find each other. The generic rpath pass
# further down only sets an RPATH on files that have none, so set these explicitly here
# to guarantee $ORIGIN regardless of what the SDK ships with. Matched by pattern rather
# than by name so that a renamed or added library in a future SDK drop does not fail the
# build.
find "$INSTALL_DIR/lib" -maxdepth 1 -type f \( -name '*Adp*.so' -o -name '*Adsk*.so' \) \
-exec patchelf --set-rpath '$ORIGIN' {} +

# Install dependencies not available on Deadline Cloud service-managed fleets
# from the system package manager, dnf.
mkdir -p "$SRC_DIR/download"
cd "$SRC_DIR/download"
dnf download --resolve -y freetype alsa-lib fontconfig harfbuzz libbrotli graphite2 \
libxkbfile xcb-util-wm xcb-util-keysyms libxkbcommon-x11 \
libva libvdpau pciutils-libs \
openjpeg2 libatomic

for RPM_FILE in *.rpm; do
rpm2cpio "$RPM_FILE" | cpio -idm
done

# Use patchelf to add relative RPATHs to the .so files where necessary.
# This is to follow the recommendation of https://docs.conda.io/projects/conda-build/en/latest/resources/use-shared-libraries.html
# to never use LD_LIBRARY_PATH in Conda environments.

# The Maya RPM has libraries in both $MAYA_ROOT/lib and $MAYA_ROOT/lib/el9
patchelf --add-rpath '$ORIGIN/../..' "$INSTALL_DIR"/lib/python*/site-packages/*.so
patchelf --add-rpath '$ORIGIN/../..' "$INSTALL_DIR"/lib/python*/site-packages/*/*.so
patchelf --add-rpath '$ORIGIN/../..' "$INSTALL_DIR"/lib/python*/lib-dynload/*.so
patchelf --add-rpath '$ORIGIN/../../el9' "$INSTALL_DIR"/lib/python*/lib-dynload/*.so

# Copy the .so libraries to the Maya lib directory, adding to their RPATHs so they see each other
find . -type f,l -iname "*.so.*" -exec patchelf --add-rpath '$ORIGIN/.' {} \;
find . -type f,l -iname "*.so.*" -exec cp -P {} "$INSTALL_DIR/lib/" \;

# Add RPATH for libraries in $MAYA_ROOT/lib that lack one, allowing them to
# find dependencies in their own directory
for file in "$INSTALL_DIR/lib"/*; do
if file "$file" | grep -q "ELF"; then
if [[ -z "$(patchelf --print-rpath "$file")" ]]; then
patchelf --set-rpath "\$ORIGIN" "$file"
fi
fi
done

# Create symlinks
mkdir -p $PREFIX/bin
ln -r -s $PREFIX/$MAYA_ROOT/bin/maya$MAYA_VERSION $PREFIX/bin/maya$MAYA_VERSION
ln -r -s $PREFIX/$MAYA_ROOT/bin/maya$MAYA_VERSION $PREFIX/bin/maya
ln -r -s $PREFIX/$MAYA_ROOT/bin/mayapy.bin $PREFIX/bin/mayapy.bin
ln -r -s $PREFIX/$MAYA_ROOT/bin/mayapy $PREFIX/bin/mayapy
ln -r -s $PREFIX/$MAYA_ROOT/bin/Render $PREFIX/bin/Render

# Use thin client licensing configuration to use the ProductInformation.pit from the Arnold installation.
#
# To learn more, see the Autodesk article "Thin Client Licensing for Maya and MotionBuilder"
# at https://www.autodesk.com/support/technical/article/caas/tsarticles/ts/2zqRBCuGDrcPZDzULJQ27p.html
# and the Arnold support tip "error: (44) Product key not found"
# at https://arnoldsupport.com/2022/02/02/error-44-product-key-not-found/.

# In Maya 2027 the Arnold payload ships as Packages/package.tgz, where earlier
# releases used Packages/package.zip.
tar -xzf "$SRC_DIR/installer/Packages/package.tgz" -C "$INSTALL_DIR/lib" \
--strip-components=1 bin/ProductInformation.pit

cat <<EOF > "$INSTALL_DIR"/AdlmThinClientCustomEnv.xml
<?xml version="1.0" encoding="utf-8"?>
<ADLMCUSTOMENV VERSION="1.0.0.0">
<PLATFORM OS="Linux">
<KEY ID="ADLM_PIT_FILE_LOCATION">
<!--Path to the ProductInformation.pit file-->
<!--Default: /var/opt/Autodesk/Adlm/.config-->
<STRING>$INSTALL_DIR/lib</STRING>
</KEY>
</PLATFORM>
</ADLMCUSTOMENV>
EOF

# Set environment variables using the JSON env_vars.d mechanism.
# See https://rattler-build.prefix.dev/latest/special_files/ for details.
# This is more portable than activation scripts and works with pixi trampolines.
mkdir -p "$PREFIX/etc/conda/env_vars.d"
cat > "$PREFIX/etc/conda/env_vars.d/$PKG_NAME-$PKG_VERSION.json" << EOF
{
"MAYA_LOCATION": "$PREFIX/$MAYA_ROOT",
"MAYA_VERSION": "$MAYA_VERSION",
"MAYA_NO_HOME": "1",
"MAYA_MODULE_PATH": "$PREFIX/usr/autodesk/maya$MAYA_VERSION/modules:$PREFIX/usr/autodesk/modules/maya/$MAYA_VERSION:$PREFIX/usr/autodesk/modules/maya",
"AUTODESK_ADLM_THINCLIENT_ENV": "$INSTALL_DIR/AdlmThinClientCustomEnv.xml",
"MAYA_LEGACY_THINCLIENT": "1",
"MAYA_DISABLE_ADP": "1",
"MAYA_DISABLE_CIP": "1",
"MAYA_DISABLE_CER": "1"
}
EOF

# --- Plugin Sync ---
# Copies the plugin delivery scripts into the conda activate.d/deactivate.d
# directories. These run AFTER the main Maya env vars are set via env_vars.d.
#
# See zzz-maya-plugin-sync-activate.sh for the full implementation.
mkdir -p "$PREFIX/etc/conda/activate.d"
cp $RECIPE_DIR/zzz-maya-plugin-sync-activate.sh \
$PREFIX/etc/conda/activate.d/zzz-$PKG_NAME-$PKG_VERSION-plugin-sync.sh

mkdir -p "$PREFIX/etc/conda/deactivate.d"
cp $RECIPE_DIR/zzz-maya-plugin-sync-deactivate.sh \
$PREFIX/etc/conda/deactivate.d/zzz-$PKG_NAME-$PKG_VERSION-plugin-sync.sh
40 changes: 40 additions & 0 deletions conda_recipes/maya-2027/recipe/meta.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Recipe in conda-build format.

# See https://docs.conda.io/projects/conda-build/en/latest/resources/define-metadata.html for information
# about this file.

{% set version = "2027.0" %}
{% set major_version = "2027" %}
{% set minor_version = "0" %}

package:
name: maya
version: {{ version }}

source:
url: archive_files/Autodesk_Maya_{{ major_version }}_Linux_64bit.tgz
sha256: c713ce176972268284a740bff6d346e01e03511c9bf0f090128f63f001ac8cf6
folder: installer

build:
number: 0
detect_binary_files_with_prefix: false
binary_relocation: false
missing_dso_whitelist:
- "**"

requirements:
build:
- patchelf
Comment thread
andrew-fenton marked this conversation as resolved.
- unzip

test:
commands:
- mayapy --help
- mayapy -c 'import maya; import maya.standalone; import maya.OpenMaya as om1; import maya.api.OpenMaya as om2; maya.standalone.initialize(); print("Hello from mayapy"); maya.standalone.uninitialize()'
- maya -batch -command 'print "Hello from maya -batch"; quit -exitCode 0 -force'

about:
home: https://www.autodesk.com/products/maya/overview
license: LicenseRef-AutodeskEULA
summary: Maya is professional 3D software for creating realistic characters and blockbuster-worthy effects.
48 changes: 48 additions & 0 deletions conda_recipes/maya-2027/recipe/recipe.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Recipe in rattler-build format.
# See https://prefix-dev.github.io/rattler-build/latest/

context:
version: "2027.0"
major_version: "2027"
minor_version: "0"

package:
name: maya
version: ${{ version }}

source:
path: ../../archive_files/Autodesk_Maya_${{ major_version }}_Linux_64bit.tgz
sha256: c713ce176972268284a740bff6d346e01e03511c9bf0f090128f63f001ac8cf6
target_directory: installer

build:
number: 0
# These build options for repackaging an application
# https://prefix-dev.github.io/rattler-build/latest/build_options/#prefix-detection-replacement-options
prefix_detection:
ignore_binary_files: True
# https://prefix-dev.github.io/rattler-build/latest/build_options/#dynamic-linking-configuration
dynamic_linking:
binary_relocation: False
missing_dso_allowlist:
- "**"

requirements:
build:
- patchelf
- unzip

tests:
- script:
# Maya's Python interpreter
- mayapy --help
# Confirm that mayapy can initialize maya.standalone, and that both OpenMaya 1.0 and 2.0 are available
- mayapy -c 'import maya; import maya.standalone; import maya.OpenMaya as om1; import maya.api.OpenMaya as om2; maya.standalone.initialize(); print("Hello from mayapy"); maya.standalone.uninitialize()'
# The maya -batch command
- maya -batch -command 'print "Hello from maya -batch"; quit -exitCode 0 -force'


about:
homepage: https://www.autodesk.com/products/maya/overview
license: LicenseRef-AutodeskEULA
summary: Maya is professional 3D software for creating realistic characters and blockbuster-worthy effects.
61 changes: 61 additions & 0 deletions conda_recipes/maya-2027/recipe/zzz-maya-plugin-sync-activate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash
# Plugin Sync for Maya
# Downloads plugin files from S3 and configures MAYA_MODULE_PATH.
# Runs after all standard Maya env vars are set via env_vars.d.
#
# S3 convention: s3://<bucket>/<prefix>/plugins/<os>/maya/<version>/
# Generic path: s3://<bucket>/<prefix>/plugins/generic/
#
# Required environment variables (set by the worker agent):
# DEADLINE_JA_S3_BUCKET - Job attachment S3 bucket name
# DEADLINE_JA_ROOT_PREFIX - Job attachment root prefix in the bucket
# OPENJD_SESSION_WORKING_DIR - Session working directory path

# Skip if the required env vars aren't available (e.g. local testing without
# the worker agent, or the worker agent hasn't been updated yet).
if [ -z "${DEADLINE_JA_S3_BUCKET:-}" ] || [ -z "${MAYA_VERSION:-}" ]; then
echo "Plugin Sync: Skipping — DEADLINE_JA_S3_BUCKET or MAYA_VERSION not set."
return 0 2>/dev/null || exit 0
fi

_SP_PREFIX="${DEADLINE_JA_ROOT_PREFIX:+${DEADLINE_JA_ROOT_PREFIX}/}"
_SP_OS="linux"
if [ "$(uname -s)" = "MINGW"* ] || [ "$(uname -s)" = "MSYS"* ] || [ -n "${OS:-}" ]; then
Comment thread
andrew-fenton marked this conversation as resolved.
_SP_OS="windows"
fi

# Determine plugin download directory
_SP_PLUGIN_DIR="${OPENJD_SESSION_WORKING_DIR:-${TMPDIR:-/tmp}}/deadline-plugins/maya"
mkdir -p "$_SP_PLUGIN_DIR"

# Download generic plugins to the session working directory
_SP_GENERIC_DIR="${OPENJD_SESSION_WORKING_DIR:-${TMPDIR:-/tmp}}/deadline-plugins/generic"
_SP_GENERIC_SRC="s3://${DEADLINE_JA_S3_BUCKET}/${_SP_PREFIX}plugins/generic/"
if [ -n "${OPENJD_SESSION_WORKING_DIR:-}" ]; then
if aws s3 ls "$_SP_GENERIC_SRC" >/dev/null 2>&1; then
echo "Plugin Sync: Downloading plugins from $_SP_GENERIC_SRC"
aws s3 cp "$_SP_GENERIC_SRC" "$_SP_GENERIC_DIR" --recursive --quiet 2>/dev/null || true
Comment thread
andrew-fenton marked this conversation as resolved.
fi
fi

# Download Maya-specific plugins
_SP_DCC_SRC="s3://${DEADLINE_JA_S3_BUCKET}/${_SP_PREFIX}plugins/${_SP_OS}/maya/${MAYA_VERSION}/"

if aws s3 ls "$_SP_DCC_SRC" >/dev/null 2>&1; then
echo "Plugin Sync: Downloading Maya plugins from $_SP_DCC_SRC"
aws s3 cp "$_SP_DCC_SRC" "$_SP_PLUGIN_DIR/" --recursive --quiet 2>/dev/null || true
Comment thread
andrew-fenton marked this conversation as resolved.
fi

# Append to MAYA_MODULE_PATH if we downloaded any files
if [ -d "$_SP_PLUGIN_DIR" ] && [ -n "$(ls -A "$_SP_PLUGIN_DIR" 2>/dev/null)" ]; then
export MAYA_MODULE_PATH="${_SP_PLUGIN_DIR}:${MAYA_MODULE_PATH:-}"
echo "Plugin Sync: MAYA_MODULE_PATH updated with $_SP_PLUGIN_DIR"
else
echo "Plugin Sync: No Maya plugins found, skipping."
fi

# Export for deactivate script cleanup
export _MAYA_PLUGIN_SYNC_DIR="$_SP_PLUGIN_DIR"

# Clean up temp variables
unset _SP_PREFIX _SP_OS _SP_PLUGIN_DIR _SP_GENERIC_SRC _SP_DCC_SRC
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/bash
# Plugin Sync for Maya — deactivate script
# Cleans up downloaded plugin files.

if [ -n "${_MAYA_PLUGIN_SYNC_DIR:-}" ] && [ -d "$_MAYA_PLUGIN_SYNC_DIR" ]; then
rm -rf "$_MAYA_PLUGIN_SYNC_DIR"
Comment thread
andrew-fenton marked this conversation as resolved.
fi
unset _MAYA_PLUGIN_SYNC_DIR
Loading