diff --git a/.github/workflows/build-usd-exchange.yml b/.github/workflows/build-usd-exchange.yml new file mode 100644 index 00000000000..254c022d183 --- /dev/null +++ b/.github/workflows/build-usd-exchange.yml @@ -0,0 +1,327 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# Mirrors upstream's repo_man build (tools/repoman/cmake_build.py, install_usdex.py, +# py_package.py) and its whl test suite (tools/pyproject/pytest.sh), narrowed to riscv64. +# Upstream links prebuilt packman OpenUSD/MaterialX/oneTBB packages with no riscv64 +# flavor, so the same stock OpenUSD release is built here with build_usd.py instead. +name: Build usd-exchange wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/usd-exchange.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-usd-exchange.yml' + - 'docs/packages/usd-exchange.yaml' + - 'patches/usd-exchange/**' + push: + branches: [main] + paths: + - '.github/workflows/build-usd-exchange.yml' + - 'docs/packages/usd-exchange.yaml' + - 'patches/usd-exchange/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: usd-exchange + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build usd-exchange ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 1440 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # Upstream's usd_flavors.json and requires-python stop at 3.13. + python: ["cp310", "cp311", "cp312", "cp313"] + + env: + USD_EXCHANGE_VERSION: ${{ matrix.version }} + + steps: + - name: Checkout usd-exchange v${{ env.USD_EXCHANGE_VERSION }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: NVIDIA-Omniverse/usd-exchange + ref: v${{ env.USD_EXCHANGE_VERSION }} + persist-credentials: false + + - name: Resolve the OpenUSD release of the default flavor + id: usd + run: | + set -euo pipefail + usd_ver="$(sed -n 's/^default_flavor = "usd_\([0-9.]*\)_py_.*"$/\1/p' repo.toml)" + test -n "${usd_ver}" + printf 'ver=%s\ntag=v%s\n' "${usd_ver}" "${usd_ver}" >> "$GITHUB_OUTPUT" + + - name: Checkout OpenUSD ${{ steps.usd.outputs.tag }} + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: PixarAnimationStudios/OpenUSD + ref: ${{ steps.usd.outputs.tag }} + path: OpenUSD + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + fetch-depth: 1 + persist-credentials: false + + - name: Patch OpenUSD + run: git -C OpenUSD apply "${GITHUB_WORKSPACE}"/python-wheels/patches/usd-exchange/${{ env.USD_EXCHANGE_VERSION }}/00*.patch + + - name: Pull manylinux_riscv64 image + run: docker pull "${MANYLINUX_RISCV64_IMAGE}" + + - name: Build OpenUSD, usd-exchange and the wheel + run: | + mkdir -p dist + docker run -i --rm \ + -v "${GITHUB_WORKSPACE}:/work" \ + -w /work \ + -e PYTHON_TAG="${{ matrix.python }}" \ + -e USD_EXCHANGE_VERSION \ + -e USD_VER="${{ steps.usd.outputs.ver }}" \ + "${MANYLINUX_RISCV64_IMAGE}" bash -s <<'USDEX_BUILD_EOF' + #!/usr/bin/env bash + set -euxo pipefail + + PY_ROOT="/opt/python/${PYTHON_TAG}-${PYTHON_TAG}" + PY="${PY_ROOT}/bin/python" + PY_VER="$("$PY" -c 'import sys; print("%d.%d" % sys.version_info[:2])')" + "$PY" -m pip install build toml wheel "pybind11==2.11.1" + + # The manylinux image ships no libpython (PEP 513); FindPython's Development + # component needs the file to exist, and nothing ends up linking against it. + "$PY" -c "import pathlib,sysconfig; pathlib.Path(sysconfig.get_config_var('LIBDIR'), sysconfig.get_config_var('LDLIBRARY')).touch()" + + # MaterialX's installed MaterialXConfig.cmake runs find_dependency(X11 COMPONENTS Xt) + # on every non-Apple Unix, even with MATERIALX_BUILD_RENDER=OFF, so OpenUSD's and + # usdex's find_package(MaterialX) need the headers; nothing links against X11. + dnf install -y --setopt=install_weak_deps=False libX11-devel libXt-devel + + USD=/work/_build/usd + # usdex only ships MaterialXCore/Format; the render modules want OpenGL and X11. + # OpenUSD 26.08 defaults PXR_PYTHON_INSTALL_DIR to lib/pythonX.Y/site-packages; + # pin the lib/python layout of upstream's packman OpenUSD, which install_usdex.py + # (and the staging below) reads pxr from. + "$PY" OpenUSD/build_scripts/build_usd.py --onetbb \ + --build-args USD,"-DPXR_PY_UNDEFINED_DYNAMIC_LOOKUP=ON -DPXR_BUILD_EXEC=OFF -DPXR_PYTHON_INSTALL_DIR=lib/python" \ + MaterialX,"-DMATERIALX_BUILD_RENDER=OFF" \ + --no-imaging --no-tools --no-examples --no-tutorials \ + --build /work/_build/usd-build --src /work/_build/usd-src "${USD}" -v + + cmake -S /work -B /work/_build/cmake \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INSTALL_LIBDIR=lib \ + -DUSDEX_INSTALL_PYTHONDIR=python \ + -DUSDEX_USD_ROOT="${USD}" \ + -DUSDEX_TBB_ROOT="${USD}" \ + -DUSDEX_MATERIALX_ROOT="${USD}" \ + -DUSDEX_VERSION_STRING="${USD_EXCHANGE_VERSION}" \ + -DUSDEX_PYBIND11_INCLUDE_DIR="$("$PY" -c 'import pybind11; print(pybind11.get_include())')" \ + -DUSDEX_PYTHON_VERSION="${PY_VER}" \ + -DUSDEX_PYTHON_ROOT="${PY_ROOT}" + cmake --build /work/_build/cmake --config Release -j "$(nproc)" + cmake --install /work/_build/cmake --config Release --prefix /work/_build/install + + "$PY" - <<'STAGE_EOF' + import glob, importlib.metadata, os, shutil, sys, toml + + usd ="/work/_build/usd" + usdex = "/work/_build/install" + staging = "/work/_build/pyproject" + libs = f"{staging}/usd_exchange.libs" + usd_ver = os.environ["USD_VER"] + major, minor = (int(x) for x in usd_ver.split(".")) + + def copy(src, dst): + os.makedirs(os.path.dirname(dst), exist_ok=True) + (shutil.copytree if os.path.isdir(src) else shutil.copyfile)(src, dst) + + for sub in ("core", "rtx", "test"): + shutil.copytree(f"{usdex}/python/usdex/{sub}", f"{staging}/usdex/{sub}") + + plugins = ["ar", "sdf", "sdr", "usd", "usdGeom", "usdLux", "usdMtlx", "usdPhysics", "usdShade", "usdShaders", "usdUI"] + schemas = ["usdMedia", "usdProc", "usdRender", "usdSemantics", "usdSkel", "usdVol"] + validators = ["usdValidation", "usdGeomValidators", "usdPhysicsValidators", "usdShadeValidators", "usdSkelValidators", "usdUtilsValidators"] + modules = ["Ar", "Gf", "Kind", "Pcp", "Plug", "Sdf", "Sdr", "Tf", "Trace", "Ts", "Usd", "UsdGeom", "UsdLux", "UsdPhysics", "UsdShade", "UsdUI", "UsdUtils", "Vt", "Work", + "UsdMedia", "UsdMtlx", "UsdProc", "UsdRender", "UsdSemantics", "UsdSkel", "UsdVol", "UsdValidation"] + if (major, minor) < (25, 8): + plugins.append("ndr") + modules.append("Ndr") + if (major, minor) >= (26, 8): + schemas += ["usdLod", "usdProfiles"] + validators.append("usdLuxValidators") + modules += ["UsdLod", "UsdProfiles"] + + copy(f"{usd}/lib/usd/plugInfo.json", f"{libs}/usd/plugInfo.json") + for plugin in plugins + schemas + validators: + for root in (f"{usd}/lib/usd", f"{usd}/plugin/usd"): + if os.path.exists(f"{root}/{plugin}"): + copy(f"{root}/{plugin}", f"{libs}/usd/{plugin}") + break + else: + sys.exit(f"plugin {plugin} not found") + copy(f"{usd}/plugin/usd/usdShaders.so", f"{libs}/usd/usdShaders.so") + for name in validators: + if name.endswith("Validators"): + copy(f"{usd}/lib/libusd_{name}.so", f"{libs}/libusd_{name}.so") + + mtlx = f"{libs}/usd/usdMtlx/resources/libraries" + for src in glob.glob(f"{usd}/libraries/bxdf/*open_pbr_surface.mtlx"): + copy(src, f"{mtlx}/bxdf/{os.path.basename(src)}") + for name in ("stdlib_defs.mtlx", "stdlib_ng.mtlx"): + copy(f"{usd}/libraries/stdlib/{name}", f"{mtlx}/stdlib/{name}") + + for module in modules: + src = f"{usd}/lib/python/pxr/{module}" + lib = "_" + module[0].lower() + module[1:] + for path in glob.glob(f"{src}/*.py") + glob.glob(f"{src}/*.pyi") + glob.glob(f"{src}/{lib}*.so"): + copy(path, f"{staging}/pxr/{module}/{os.path.basename(path)}") + if not glob.glob(f"{staging}/pxr/{module}/{lib}*.so"): + sys.exit(f"pxr.{module} has no {lib} binding") + + notices = { + "materialx-LICENSE.txt": glob.glob("/work/_build/usd-src/MaterialX-*/LICENSE")[0], + "onetbb-LICENSE.txt": glob.glob("/work/_build/usd-src/oneTBB-*/LICENSE.txt")[0], + "openusd-LICENSE.txt": "/work/OpenUSD/LICENSE.txt", + "pybind11-LICENSE.txt": [f for f in importlib.metadata.files("pybind11") if f.name == "LICENSE"][0].locate(), + "pyboost11-LICENSE.txt": "/work/tools/internal-licenses/pyboost11-LICENSE.txt", + "usd-exchange-LICENSE.md": "/work/LICENSE.md", + } + for name, src in notices.items(): + copy(src, f"{staging}/{name}") + + validator_version = toml.load("/work/tools/repoman/repo_tools.toml")["repo_install_usdex"]["usd_validation_version"] + data = toml.load("/work/tools/pyproject/pyproject.toml") + data["project"]["version"] = os.environ["USD_EXCHANGE_VERSION"] + data["project"]["optional-dependencies"].update({ + "usd" + usd_ver.replace(".", ""): [], + "test": [f"usd-validation-nvidia>={validator_version},<{int(validator_version.split('.')[0]) + 1}"], + }) + with open(f"{staging}/pyproject.toml", "w") as f: + toml.dump(data, f) + with open("/work/README.md") as f: + readme = f.readlines()[4:7] + with open("/work/tools/pyproject/pypi-notice.md") as f: + notice = f.read() + with open(f"{staging}/README.md", "w") as f: + f.writelines(readme) + f.write(f"\n{notice}") + shutil.copyfile("/work/tools/pyproject/hatch_build.py", f"{staging}/hatch_build.py") + STAGE_EOF + + # Upstream strips before auditwheel's patchelf, never after it. + find /work/_build/pyproject /work/_build/usd/lib /work/_build/install/lib -name '*.so*' -type f \ + -exec sh -c 'head -c4 "$1" | grep -q ELF && strip "$1"' _ {} \; + + "$PY" -m build --wheel --outdir /work/_build/pyproject/dist /work/_build/pyproject + LD_LIBRARY_PATH="/work/_build/install/lib:/work/_build/usd/lib:${LD_LIBRARY_PATH:-}" \ + auditwheel repair -w /work/_build/wheelhouse /work/_build/pyproject/dist/*.whl + + "$PY" - <<'PLUGINFO_EOF' + import glob, json, os, re, subprocess, sys, tempfile + + wheel = glob.glob("/work/_build/wheelhouse/*.whl")[0] + with tempfile.TemporaryDirectory() as tmp: + subprocess.run([sys.executable, "-m", "wheel", "unpack", wheel, "--dest", tmp], check=True) + unpacked = glob.glob(f"{tmp}/*/")[0].rstrip("/") + libs_root = f"{unpacked}/usd_exchange.libs" + hashed = {} + for lib in glob.glob(f"{libs_root}/*.so*"): + match = re.match(r"^(lib.+?)-[0-9a-f]{6,}\.so", os.path.basename(lib)) + if match: + hashed[match.group(1)] = os.path.basename(lib) + for plug_info in glob.glob(f"{libs_root}/usd/*/resources/plugInfo.json"): + with open(plug_info) as f: + data = json.loads("".join(line for line in f if not line.lstrip().startswith("#"))) + modified = False + for plug in data.get("Plugins", []): + lib = hashed.get(f"libusd_{plug.get('Name')}") + if lib and "LibraryPath" in plug: + plug["LibraryPath"] = f"../../{lib}" + modified = True + if modified: + with open(plug_info, "w") as f: + json.dump(data, f, indent=4) + subprocess.run([sys.executable, "-m", "wheel", "pack", unpacked, "--dest-dir", "/work/dist"], check=True) + PLUGINFO_EOF + ls -la /work/dist + USDEX_BUILD_EOF + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: usd-exchange-${{ env.USD_EXCHANGE_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: dist/*.whl + if-no-files-found: error + + - name: Test usd-exchange wheel + run: | + docker run -i --rm \ + -v "${GITHUB_WORKSPACE}:/work" \ + -w /work \ + -e PYTHON_TAG="${{ matrix.python }}" \ + "${MANYLINUX_RISCV64_IMAGE}" bash -s <<'USDEX_TEST_EOF' + #!/usr/bin/env bash + set -euxo pipefail + + VENV=/tmp/venv + "/opt/python/${PYTHON_TAG}-${PYTHON_TAG}/bin/python" -m venv "${VENV}" + "${VENV}/bin/python" -m pip install -U pip + wheel="$(echo /work/dist/*.whl)" + "${VENV}/bin/python" -m pip install "${wheel}[test]" + + # usdex's own test extra declares usd-validation-nvidia as an open range (py_package.py), so pip installs + # whatever is newest; usdex.test's ValidationRules only recognizes the exact release pinned in + # repo_tools.toml (a newer one can rename the native-validator adapter it registers, which breaks the + # ShaderSdrCompliance issue filter in testMaterialAlgo.py - see CLAUDE.md gotcha 629), so repin exactly. + usd_validation_version="$(sed -n 's/^usd_validation_version = "\(.*\)"$/\1/p' tools/repoman/repo_tools.toml)" + "${VENV}/bin/python" -m pip install "usd-validation-nvidia==${usd_validation_version}" + + unset PYTHONPATH + "${VENV}/bin/python" tools/pyproject/check_wheel_imports.py + "${VENV}/bin/python" -m unittest discover -v -s source/core/tests/unittest + "${VENV}/bin/python" -m unittest discover -v -s source/rtx/tests/unittest + USDEX_TEST_EOF + + publish: + name: Publish usd-exchange ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: usd-exchange-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/usd-exchange.yaml b/docs/packages/usd-exchange.yaml new file mode 100644 index 00000000000..9a5bb7e5f0c --- /dev/null +++ b/docs/packages/usd-exchange.yaml @@ -0,0 +1,6 @@ +package-name: usd-exchange +source-code: https://github.com/NVIDIA-Omniverse/usd-exchange +license: Apache-2.0 +versions: +- version: 3.0.0 + patched: true diff --git a/patches/usd-exchange/3.0.0/0001-Support-riscv64-in-pxr-base-arch.patch b/patches/usd-exchange/3.0.0/0001-Support-riscv64-in-pxr-base-arch.patch new file mode 100644 index 00000000000..a022f2e8a1c --- /dev/null +++ b/patches/usd-exchange/3.0.0/0001-Support-riscv64-in-pxr-base-arch.patch @@ -0,0 +1,121 @@ +From e346d5ee838ae79333ed9e0f6242891c841ed1b8 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Mon, 21 Sep 2026 01:53:09 +0000 +Subject: [PATCH] Support riscv64 in pxr/base/arch + +pxr/base/arch/defines.h recognises only x86 and ARM, and its "Bits" block +ends in #error "Unsupported architecture. x86_64 or ARM64 required." - so +every translation unit of USD fails on riscv64 before anything else is +compiled. Two further sites are reached once that is fixed: arch/math.h +guards ArchSign/ArchFloatToBitPattern/... on +ARCH_CPU_INTEL || ARCH_CPU_ARM || ARCH_OS_WASM_VM and ends in #error Unknown +system architecture (the code it guards is portable IEEE-754 bit twiddling, +not x86 or ARM specific), and nonLockingLinux__execve() in +arch/stackTrace.cpp has hand-written syscall asm for aarch64 and x86_64 with +#error Unknown architecture in the #else. + +Add an ARCH_CPU_RISCV define for __riscv, admit __riscv_xlen == 64 to +ARCH_BITS_64, let math.h's gate accept it, and give +nonLockingLinux__execve() a riscv64 branch. The syscall branch mirrors the +aarch64 one exactly: the Linux riscv64 ABI passes arguments in a0-a2, takes +the syscall number in a7, uses the same generic __NR_execve == 221 as +aarch64, and traps with ecall instead of svc. Everything else in arch is +already portable: ARCH_SPIN_PAUSE() has a no-op #else, timing.h only reaches +rdtsc behind PXR_ARCH_PREFER_TSC_TIMING and otherwise uses +std::chrono::steady_clock, and the remaining #error branches in +systemInfo.cpp/fileSystem.cpp/assumptions.cpp select on the OS, not the CPU. + +With this, the core (non-imaging) USD libraries and their Python bindings +build and run on riscv64; pxr/base/gf's SIMD paths are already gated on +__SSE2__/__ARM_NEON with scalar fallbacks, and the vendored +double-conversion already lists __riscv. + +Upstream-Status: To upstream [not submitted from this automated port run; needs a pull request against PixarAnimationStudios/OpenUSD] +--- + pxr/base/arch/defines.h | 7 +++++-- + pxr/base/arch/math.h | 1 + + pxr/base/arch/overview.dox | 1 + + pxr/base/arch/stackTrace.cpp | 14 ++++++++++++++ + 4 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/pxr/base/arch/defines.h b/pxr/base/arch/defines.h +index b7ed634..58e860c 100644 +--- a/pxr/base/arch/defines.h ++++ b/pxr/base/arch/defines.h +@@ -39,6 +39,8 @@ + #elif defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || \ + defined(_M_ARM64) + #define ARCH_CPU_ARM ++#elif defined(__riscv) ++#define ARCH_CPU_RISCV + #endif + + // +@@ -46,12 +48,13 @@ + // + + #if defined(__x86_64__) || defined(__aarch64__) || defined(_M_X64) || \ +- defined(_M_ARM64) || defined(__wasm64__) ++ defined(_M_ARM64) || defined(__wasm64__) || \ ++ (defined(__riscv) && __riscv_xlen == 64) + #define ARCH_BITS_64 + #elif defined(__wasm32__) + #define ARCH_BITS_32 + #else +-#error "Unsupported architecture. x86_64 or ARM64 required." ++#error "Unsupported architecture. x86_64, ARM64 or RISC-V 64 required." + #endif + + // +diff --git a/pxr/base/arch/math.h b/pxr/base/arch/math.h +index ccd53a6..8191023 100644 +--- a/pxr/base/arch/math.h ++++ b/pxr/base/arch/math.h +@@ -30,6 +30,7 @@ PXR_NAMESPACE_OPEN_SCOPE + ///@{ + + #if defined (ARCH_CPU_INTEL) || defined (ARCH_CPU_ARM) || \ ++ defined (ARCH_CPU_RISCV) || \ + defined(ARCH_OS_WASM_VM) || defined (doxygen) + + /// This is the smallest value e such that 1+e^2 == 1, using floats. +diff --git a/pxr/base/arch/overview.dox b/pxr/base/arch/overview.dox +index b8eaf9b..045375b 100644 +--- a/pxr/base/arch/overview.dox ++++ b/pxr/base/arch/overview.dox +@@ -64,6 +64,7 @@ For processor: + + + For bits: +diff --git a/pxr/base/arch/stackTrace.cpp b/pxr/base/arch/stackTrace.cpp +index 384959e..6a90d38 100644 +--- a/pxr/base/arch/stackTrace.cpp ++++ b/pxr/base/arch/stackTrace.cpp +@@ -878,6 +878,20 @@ nonLockingLinux__execve (const char *file, + ); + result = __file_result; + } ++#elif defined (ARCH_CPU_RISCV) && defined(ARCH_BITS_64) ++ { ++ long __file_result asm ("a0") = (long)file; ++ char* const* __argv asm ("a1") = argv; ++ char* const* __envp asm ("a2") = envp; ++ long __num_execve asm ("a7") = 221; ++ __asm__ __volatile__ ( ++ "ecall" ++ : "=r" (__file_result) ++ : "r"(__num_execve), "r" (__file_result), "r" (__argv), "r" (__envp) ++ : "memory" ++ ); ++ result = __file_result; ++ } + #elif defined(ARCH_CPU_INTEL) && defined(ARCH_BITS_64) + + /* +-- +2.43.0 + diff --git a/patches/usd-exchange/3.0.0/0002-Skip-the-cache-line-size-assumption-check-on-riscv64.patch b/patches/usd-exchange/3.0.0/0002-Skip-the-cache-line-size-assumption-check-on-riscv64.patch new file mode 100644 index 00000000000..23a83b30b70 --- /dev/null +++ b/patches/usd-exchange/3.0.0/0002-Skip-the-cache-line-size-assumption-check-on-riscv64.patch @@ -0,0 +1,61 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Sun, 4 Oct 2026 01:30:19 +0000 +Subject: [PATCH] Skip the cache-line size assumption check on riscv64 + +Arch_ValidateAssumptions() runs on every load of libusd_arch and compares +ARCH_CACHE_LINE_SIZE (pxr/base/arch/align.h: 128 on Apple ARM, 64 everywhere +else) with Arch_ObtainCacheLineSize(), i.e. sysconf(_SC_LEVEL1_DCACHE_LINESIZE) +on Linux. On a mismatch it prints a four-line " ArchWarn: ARCH_CACHE_LINE_SIZE +!= Arch_ObtainCacheLineSize()" block straight to stderr with fprintf +(arch/error.cpp), below the Tf diagnostics layer, so no environment setting or +diagnostic delegate can silence it. + +On riscv64 the comparison has nothing to check. The ISA defines no cache-line +size; it varies between implementations. glibc's riscv sysconf reads it from +the AT_L1D_CACHEGEOMETRY auxv entry, which the kernel fills from the +firmware's devicetree/ACPI cache description and sets to 0 when there is none +(arch/riscv/kernel/cacheinfo.c). Whatever value align.h picks for riscv64 is +therefore "wrong" on some machines, and the warning fires on every process +that imports pxr on those machines: every user of the wheel sees it, and +every test that checks a subprocess's stderr exactly fails because of it +(usd-exchange's testDiagnostics.py assertOutputStreams() and +testSettings.py's empty-stderr assertion). + +Keep ARCH_CACHE_LINE_SIZE at its 64 default (it only sizes padding and +alignment, so a mismatch costs performance, never correctness) and skip the +comparison when ARCH_CPU_RISCV is defined (added by the previous patch). The +other checks in Arch_ValidateAssumptions(), including the big-endian +ARCH_ERROR, are unchanged. + +Upstream-Status: To upstream [not submitted from this automated port run; belongs with the riscv64 arch support of the previous patch in a pull request against PixarAnimationStudios/OpenUSD] +--- + pxr/base/arch/assumptions.cpp | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/pxr/base/arch/assumptions.cpp b/pxr/base/arch/assumptions.cpp +index 1029b32..f0c63df 100644 +--- a/pxr/base/arch/assumptions.cpp ++++ b/pxr/base/arch/assumptions.cpp +@@ -135,10 +135,18 @@ Arch_ValidateAssumptions() + /* + * Make sure that the ARCH_CACHE_LINE_SIZE constant is set as expected + * on the current hardware architecture. ++ * ++ * RISC-V has no architectural cache-line size: it varies between ++ * implementations, and Linux reports whatever the firmware describes ++ * (0 when it describes none), so there is no constant to validate. + */ ++#if !defined(ARCH_CPU_RISCV) + if (ARCH_CACHE_LINE_SIZE != cacheLineSize) { + ARCH_WARNING("ARCH_CACHE_LINE_SIZE != Arch_ObtainCacheLineSize()"); + } ++#else ++ (void)cacheLineSize; ++#endif + + /* + * Make sure that the machine is little-endian. We do not support +-- +2.43.0 +