From 0b6ca0bd7b12f8061e3aca97e35b4261562047a0 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 19:33:06 -0700 Subject: [PATCH 01/11] Re-enable shadow-hand rendering and Isaac Sim PhysX training tests on ARM The ARM pool grew from two DGX Spark runners to eighteen, so the two tests dropped from ARM coverage run again: the shadow-hand kit-less rendering test regains its arm_ci marker, and the uv-run Isaac Sim PhysX Cartpole install test no longer skips on aarch64. --- source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip | 0 .../uv_run/test_uv_run_isaacsim_trains_cartpole.py | 8 -------- .../changelog.d/jichuanh-arm-ci-reenable.skip | 0 .../test/core/test_rendering_shadow_hand_kitless.py | 4 ++-- 4 files changed, 2 insertions(+), 10 deletions(-) create mode 100644 source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip create mode 100644 source/isaaclab_tasks/changelog.d/jichuanh-arm-ci-reenable.skip diff --git a/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip b/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py b/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py index 851cbba6b1f5..2b065072e99d 100644 --- a/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py +++ b/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py @@ -15,7 +15,6 @@ from __future__ import annotations -import platform import shutil import pytest @@ -52,13 +51,6 @@ class Test_Uv_Run_Isaacsim_Trains_Cartpole: def setup_class(cls): if not shutil.which("uv"): pytest.skip("uv is not available") - # PhysX training currently fails at env creation on aarch64 (DGX Spark): - # "[omni.physx.tensors.plugin] Simulation view object is invalidated and cannot - # be used again to call updateArticulationsKinematic". The environment itself - # installs fine from the lock; this matches the x86-only scope of the workflow - # this test replaces. Re-enable once PhysX training works on aarch64. - if platform.machine().lower() in ("aarch64", "arm64"): - pytest.skip("PhysX training is not functional on aarch64 yet") @pytest.mark.docker @pytest.mark.smoke diff --git a/source/isaaclab_tasks/changelog.d/jichuanh-arm-ci-reenable.skip b/source/isaaclab_tasks/changelog.d/jichuanh-arm-ci-reenable.skip new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py b/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py index ea44307f02c2..b17e9c41a0c3 100644 --- a/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py +++ b/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py @@ -19,8 +19,8 @@ rendering_test_shadow_hand, ) -# no arm_ci marker: intermittently stalls the arm64 runner mid-file (renderer hang after a few -# passing cases, killed at the per-file timeout); x86 kitless coverage remains in place +pytestmark = pytest.mark.arm_ci + _RENDERING_PARAMS = group_rendering_params( make_kitless_rendering_params(MINIMAL_KITLESS_PHYSICS_RENDERER_AOV_COMBINATIONS) ) From 89233304004df713cc78e16bcea906441d3ac752 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 19:37:00 -0700 Subject: [PATCH 02/11] Pin the multi-arch Isaac Sim CI image so ARM CI can build The 6.2.0-alpha.12 bump pinned the image's x86_64 manifest digest instead of its manifest list, so the arm64 base build pulled an amd64 image and failed with an exec format error. Pin the list digest of the same build; x86 still resolves to the identical amd64 image. --- .github/workflows/config.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/config.yaml b/.github/workflows/config.yaml index 8396578d83bb..e792a9e38cbe 100644 --- a/.github/workflows/config.yaml +++ b/.github/workflows/config.yaml @@ -9,7 +9,8 @@ # (frozen at 6.1.0-alpha.2). Both images use Isaac Sim's NGC org, which is current and # which the CI credential can reach. isaacsim_image_name: nvcr.io/0947644777160149/internal/isaac-sim -# Isaac Sim 6.2.0-alpha.12+develop.51655.36d2fc9a.gl with Kit 110.4.0-384466 -isaacsim_image_tag: latest-develop@sha256:a6c53e29d6f15ade5475e0d8b4bcff88c351a3815723ad36434e442728898c98 +# Isaac Sim 6.2.0-alpha.12+develop.51655.36d2fc9a.gl with Kit 110.4.0-384466. +# Pin the multi-arch manifest list digest, not a per-architecture one: ARM CI pulls linux/arm64. +isaacsim_image_tag: latest-develop@sha256:e78f716a1cae92d432b009e48b8d1184137515e244baefcdf8043ea48f5c4cc3 isaaclab_image_name: nvcr.io/0947644777160149/internal/isaac-lab ovphysx_wheelhouse_image: "" From d85b591df21d3d6a6abf21f5f2ba3b4b30418f91 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 20:47:54 -0700 Subject: [PATCH 03/11] Report ARM CI failures as failed workflow runs The job-level continue-on-error marked every run successful even when the arm64 build or tests failed, so a broken ARM CI looked green in the run list. The check is not required, so a failure still does not block merges. --- .github/workflows/arm-ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/arm-ci.yml b/.github/workflows/arm-ci.yml index 3e992dcef3cb..f42e587454ea 100644 --- a/.github/workflows/arm-ci.yml +++ b/.github/workflows/arm-ci.yml @@ -14,8 +14,8 @@ # it could be retried. As its own workflow, arm-ci no longer gates the main # workflow's lifecycle, and it can be re-run independently. # -# arm-ci is currently informational (continue-on-error), but it is wired to be -# promotable to a REQUIRED status check: it triggers on every PR and gates the +# arm-ci is not a required check, so a failure reports red without blocking the +# merge. It is wired to be promotable to one: it triggers on every PR and gates the # expensive arm64 build behind the shared `changes` detector + `if:`. An # irrelevant PR SKIPS the job (which branch protection reads as green) instead # of never creating the check — a workflow-level `paths:` filter is deliberately @@ -153,7 +153,6 @@ jobs: needs: [changes, config] if: needs.changes.outputs.should_run == 'true' timeout-minutes: 60 - continue-on-error: true steps: - uses: actions/checkout@v6 with: From f7b0fb35383e11c13f8a8eff553c3a2a6bc7dd3f Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:02:13 -0700 Subject: [PATCH 04/11] Move the ARM test re-enables to a follow-up PR Keep this change to the ARM CI build fix; the shadow-hand rendering and Isaac Sim PhysX Cartpole re-enables land separately after repeated Spark runs. --- source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip | 0 .../uv_run/test_uv_run_isaacsim_trains_cartpole.py | 8 ++++++++ .../changelog.d/jichuanh-arm-ci-reenable.skip | 0 .../test/core/test_rendering_shadow_hand_kitless.py | 4 ++-- 4 files changed, 10 insertions(+), 2 deletions(-) delete mode 100644 source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip delete mode 100644 source/isaaclab_tasks/changelog.d/jichuanh-arm-ci-reenable.skip diff --git a/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip b/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.skip deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py b/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py index 2b065072e99d..851cbba6b1f5 100644 --- a/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py +++ b/source/isaaclab/test/install_ci/uv_run/test_uv_run_isaacsim_trains_cartpole.py @@ -15,6 +15,7 @@ from __future__ import annotations +import platform import shutil import pytest @@ -51,6 +52,13 @@ class Test_Uv_Run_Isaacsim_Trains_Cartpole: def setup_class(cls): if not shutil.which("uv"): pytest.skip("uv is not available") + # PhysX training currently fails at env creation on aarch64 (DGX Spark): + # "[omni.physx.tensors.plugin] Simulation view object is invalidated and cannot + # be used again to call updateArticulationsKinematic". The environment itself + # installs fine from the lock; this matches the x86-only scope of the workflow + # this test replaces. Re-enable once PhysX training works on aarch64. + if platform.machine().lower() in ("aarch64", "arm64"): + pytest.skip("PhysX training is not functional on aarch64 yet") @pytest.mark.docker @pytest.mark.smoke diff --git a/source/isaaclab_tasks/changelog.d/jichuanh-arm-ci-reenable.skip b/source/isaaclab_tasks/changelog.d/jichuanh-arm-ci-reenable.skip deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py b/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py index b17e9c41a0c3..ea44307f02c2 100644 --- a/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py +++ b/source/isaaclab_tasks/test/core/test_rendering_shadow_hand_kitless.py @@ -19,8 +19,8 @@ rendering_test_shadow_hand, ) -pytestmark = pytest.mark.arm_ci - +# no arm_ci marker: intermittently stalls the arm64 runner mid-file (renderer hang after a few +# passing cases, killed at the per-file timeout); x86 kitless coverage remains in place _RENDERING_PARAMS = group_rendering_params( make_kitless_rendering_params(MINIMAL_KITLESS_PHYSICS_RENDERER_AOV_COMBINATIONS) ) From 12b861660095566abf48ae08d5d87bf322a45e88 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:18:21 -0700 Subject: [PATCH 05/11] Preload the system OpenMP runtime in the arm64 Isaac Lab image Isaac Sim exits on aarch64 unless /lib/aarch64-linux-gnu/libgomp.so.1 loads before the copy bundled with torch, so Kit-based tests such as test_operational_space failed at import in ARM CI. Add it to /etc/ld.so.preload on arm64, as the image already does for the Carbonite shim because python.sh resets LD_PRELOAD. --- docker/Dockerfile.base | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index 255ada8f4797..9ff88b9ce026 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -85,6 +85,13 @@ RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \ libx11-dev libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev; \ fi +# arm64: Isaac Sim refuses to start unless the system OpenMP runtime loads before the copy +# bundled with torch. Preload it image-wide, like the shim above, so every entry point gets it. +RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \ + test -f /lib/aarch64-linux-gnu/libgomp.so.1 && \ + printf '\n%s\n' /lib/aarch64-linux-gnu/libgomp.so.1 >> /etc/ld.so.preload; \ + fi + # copy files necessary for installing Isaac Lab and its dependencies # this way we minimize the chance of cache invalidation on file edits COPY --from=uv /uv /uvx /usr/local/bin/ From aae10cbecb88e6976692245c92333caf1a554625 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:18:27 -0700 Subject: [PATCH 06/11] Skip ovstage rendering cases in ARM CI The ovstage variants of the arm_ci kit-less rendering tests fail image comparison on arm64 and fail on x86 develop as well, where they run post-merge only. Deselect them in both ARM test steps so ARM CI reports the legacy path the required x86 job covers. --- .github/workflows/arm-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/arm-ci.yml b/.github/workflows/arm-ci.yml index f42e587454ea..9ca74d6017d5 100644 --- a/.github/workflows/arm-ci.yml +++ b/.github/workflows/arm-ci.yml @@ -183,7 +183,8 @@ jobs: container-name: isaac-lab-arm-ci-${{ github.run_id }}-${{ github.run_attempt }} image-tag: ${{ needs.config.outputs.ci_image_tag }}-arm64 extra-pip-packages: "${{ steps.ov_pins.outputs.ovrtx }} ${{ steps.ov_pins.outputs.ovphysx }}" - test-k-expr: not ovphysx + # ovstage rendering cases are post-merge only on x86 as well. + test-k-expr: not ovphysx and not ovstage ci-marker: arm_ci volume-mount-source: ${{ github.workspace }} @@ -195,7 +196,7 @@ jobs: container-name: isaac-lab-arm-ci-ovphysx-${{ github.run_id }}-${{ github.run_attempt }} image-tag: ${{ needs.config.outputs.ci_image_tag }}-arm64 extra-pip-packages: "${{ steps.ov_pins.outputs.ovrtx }} ${{ steps.ov_pins.outputs.ovphysx }}" - test-k-expr: ovphysx + test-k-expr: ovphysx and not ovstage ci-marker: arm_ci volume-mount-source: ${{ github.workspace }} From 1ec2ba3eccf5548f9d301518ca2ebb3ecf8c4384 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:18:27 -0700 Subject: [PATCH 07/11] Rewrap the ARM CI header comment to 80 columns --- .github/workflows/arm-ci.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/arm-ci.yml b/.github/workflows/arm-ci.yml index 9ca74d6017d5..a45a180a4815 100644 --- a/.github/workflows/arm-ci.yml +++ b/.github/workflows/arm-ci.yml @@ -14,14 +14,14 @@ # it could be retried. As its own workflow, arm-ci no longer gates the main # workflow's lifecycle, and it can be re-run independently. # -# arm-ci is not a required check, so a failure reports red without blocking the -# merge. It is wired to be promotable to one: it triggers on every PR and gates the -# expensive arm64 build behind the shared `changes` detector + `if:`. An -# irrelevant PR SKIPS the job (which branch protection reads as green) instead -# of never creating the check — a workflow-level `paths:` filter is deliberately -# avoided because a not-triggered required check stays pending forever and -# blocks the PR. This mirrors the `changes`+`if:` pattern build.yaml already -# uses for its required test jobs. +# arm-ci is not a required check, so a failure reports red without blocking +# the merge. It is wired to be promotable to one: it triggers on every PR and +# gates the expensive arm64 build behind the shared `changes` detector + `if:`. +# An irrelevant PR SKIPS the job (which branch protection reads as green) +# instead of never creating the check — a workflow-level `paths:` filter is +# deliberately avoided because a not-triggered required check stays pending +# forever and blocks the PR. This mirrors the `changes`+`if:` pattern +# build.yaml already uses for its required test jobs. # # Trigger parity with the former build.yaml job: # - push to protected branches always runs (post-merge integration); From f344e997ebb04b192c8b3b3a7642b12cae0074cf Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:38:21 -0700 Subject: [PATCH 08/11] Drop the image-wide libgomp preload Isaac Sim's aarch64 check reads the LD_PRELOAD variable, not /etc/ld.so.preload, so the preload did not stop test_operational_space from exiting at import. --- docker/Dockerfile.base | 7 ------- 1 file changed, 7 deletions(-) diff --git a/docker/Dockerfile.base b/docker/Dockerfile.base index 9ff88b9ce026..255ada8f4797 100644 --- a/docker/Dockerfile.base +++ b/docker/Dockerfile.base @@ -85,13 +85,6 @@ RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \ libx11-dev libxcursor-dev libxi-dev libxinerama-dev libxrandr-dev; \ fi -# arm64: Isaac Sim refuses to start unless the system OpenMP runtime loads before the copy -# bundled with torch. Preload it image-wide, like the shim above, so every entry point gets it. -RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \ - test -f /lib/aarch64-linux-gnu/libgomp.so.1 && \ - printf '\n%s\n' /lib/aarch64-linux-gnu/libgomp.so.1 >> /etc/ld.so.preload; \ - fi - # copy files necessary for installing Isaac Lab and its dependencies # this way we minimize the chance of cache invalidation on file edits COPY --from=uv /uv /uvx /usr/local/bin/ From 4055e5497d8f1ee1f8a8f2f7c2745ebfc712d72a Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:38:21 -0700 Subject: [PATCH 09/11] Preload the system libgomp in ARM CI test containers isaacsim exits at import on aarch64 unless /lib/aarch64-linux-gnu/libgomp.so.1 is listed in LD_PRELOAD, so the Kit-based arm_ci tests failed before running. Pass it to the test container on aarch64 hosts, matching the install tests' aarch64 environment. --- .github/actions/run-tests/run_tests.sh | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/actions/run-tests/run_tests.sh b/.github/actions/run-tests/run_tests.sh index 3e8545606967..6450e8692dcb 100755 --- a/.github/actions/run-tests/run_tests.sh +++ b/.github/actions/run-tests/run_tests.sh @@ -124,6 +124,12 @@ run_tests() { -e "TEST_RESULT_FILE=$result_file" ) + # On aarch64, isaacsim exits at import unless the system libgomp path is listed in + # LD_PRELOAD itself; /etc/ld.so.preload does not satisfy its check. + if [ "$(uname -m)" = "aarch64" ]; then + docker_env_args+=(-e "LD_PRELOAD=/lib/aarch64-linux-gnu/libgomp.so.1") + fi + if [ "$curobo_only" = "true" ]; then docker_env_args+=(-e "TEST_CUROBO_ONLY=true") echo "Setting TEST_CUROBO_ONLY=true" From 5f2ec8c4fae8866c1bb92825f88626cfc5205b71 Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:57:56 -0700 Subject: [PATCH 10/11] Drop the ARM CI test-container libgomp preload The CLI is the layer that already preloads libgomp for every Python it launches, including ARM CI's pytest; fix it there instead of in the CI test runner. --- .github/actions/run-tests/run_tests.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/actions/run-tests/run_tests.sh b/.github/actions/run-tests/run_tests.sh index 6450e8692dcb..3e8545606967 100755 --- a/.github/actions/run-tests/run_tests.sh +++ b/.github/actions/run-tests/run_tests.sh @@ -124,12 +124,6 @@ run_tests() { -e "TEST_RESULT_FILE=$result_file" ) - # On aarch64, isaacsim exits at import unless the system libgomp path is listed in - # LD_PRELOAD itself; /etc/ld.so.preload does not satisfy its check. - if [ "$(uname -m)" = "aarch64" ]; then - docker_env_args+=(-e "LD_PRELOAD=/lib/aarch64-linux-gnu/libgomp.so.1") - fi - if [ "$curobo_only" = "true" ]; then docker_env_args+=(-e "TEST_CUROBO_ONLY=true") echo "Setting TEST_CUROBO_ONLY=true" From 6e8879060e9b10e7bface139676524da3139cfab Mon Sep 17 00:00:00 2001 From: jichuanh Date: Wed, 30 Sep 2026 21:57:57 -0700 Subject: [PATCH 11/11] Preload the system libgomp by full path for CLI runs on aarch64 isaacsim exits at import on aarch64 unless each system /lib/*/libgomp.so.1 path is listed verbatim in LD_PRELOAD. The CLI preloaded the bare libgomp.so.1 soname, which the check rejects, so venv-based runs such as ARM CI's Kit tests still exited. Prepend the full system paths instead. --- .../jichuanh-arm-ci-reenable.fixed.rst | 3 +++ source/isaaclab/isaaclab/cli/utils.py | 16 +++++++++------- source/isaaclab/test/cli/test_install.py | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.fixed.rst diff --git a/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.fixed.rst b/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.fixed.rst new file mode 100644 index 000000000000..64295f4925d8 --- /dev/null +++ b/source/isaaclab/changelog.d/jichuanh-arm-ci-reenable.fixed.rst @@ -0,0 +1,3 @@ +* Fixed CLI runs on Linux aarch64 from a virtual environment exiting at ``isaacsim`` import with + the ``LD_PRELOAD`` banner. The CLI now preloads the system ``libgomp.so.1`` by its full path, + which is the form Isaac Sim's check accepts. diff --git a/source/isaaclab/isaaclab/cli/utils.py b/source/isaaclab/isaaclab/cli/utils.py index e96028b51833..dc2b96aee984 100644 --- a/source/isaaclab/isaaclab/cli/utils.py +++ b/source/isaaclab/isaaclab/cli/utils.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: BSD-3-Clause +import glob import os import platform import shutil @@ -630,18 +631,19 @@ def _aarch64_libgomp_env(env: dict[str, str] | None) -> dict[str, str] | None: The torch wheel bundles its own libgomp, which loads first and conflicts with the library Isaac Sim expects, so isaacsim refuses to start unless the system libgomp is preloaded. The pip installation docs tell users to export LD_PRELOAD by hand; doing it - here makes first runs through the CLI work out of the box. The bare soname is used so - ``ld.so`` resolves the library through the ldconfig cache on any distro. Returns the - env unchanged on other platforms or when a libgomp is already preloaded. + here makes first runs through the CLI work out of the box. isaacsim only accepts the + system ``/lib/*/libgomp.so.1`` paths listed verbatim, so those full paths are prepended. + Returns the env unchanged on other platforms, without a system libgomp, or when every + such path is already preloaded. """ if platform.system() != "Linux" or platform.machine().lower() not in ("aarch64", "arm64"): return env - libgomp = "libgomp.so.1" merged = dict(os.environ if env is None else env) - preload = merged.get("LD_PRELOAD", "") - if any(os.path.basename(entry) == libgomp for entry in preload.split(":") if entry): + preload = [entry for entry in merged.get("LD_PRELOAD", "").split(":") if entry] + missing = [path for path in sorted(glob.glob("/lib/*/libgomp.so.1")) if path not in preload] + if not missing: return env - merged["LD_PRELOAD"] = f"{libgomp}:{preload}" if preload else libgomp + merged["LD_PRELOAD"] = ":".join(missing + preload) return merged diff --git a/source/isaaclab/test/cli/test_install.py b/source/isaaclab/test/cli/test_install.py index 3c42873f39b8..c938039d0c10 100644 --- a/source/isaaclab/test/cli/test_install.py +++ b/source/isaaclab/test/cli/test_install.py @@ -86,6 +86,22 @@ def test_run_python_command_uses_live_isaac_sim_with_active_python(tmp_path): assert run.call_args.kwargs["env"]["PYTHONEXE"] == active_python +def test_run_python_command_preloads_system_libgomp_path_on_aarch64(tmp_path): + """isaacsim starts on aarch64 only when the system libgomp path is listed verbatim in LD_PRELOAD.""" + with ( + mock.patch("isaaclab.cli.utils.DEFAULT_ISAAC_SIM_PATH", tmp_path / "_isaac_sim"), + mock.patch("isaaclab.cli.utils.extract_python_exe", return_value=sys.executable), + mock.patch("isaaclab.cli.utils.platform.system", return_value="Linux"), + mock.patch("isaaclab.cli.utils.platform.machine", return_value="aarch64"), + mock.patch("isaaclab.cli.utils.glob.glob", return_value=["/lib/aarch64-linux-gnu/libgomp.so.1"]), + mock.patch("isaaclab.cli.utils.run_command") as run, + mock.patch.dict(os.environ, {"LD_PRELOAD": "libcarb.env.shim.so"}, clear=True), + ): + run_python_command("train.py", []) + + assert run.call_args.kwargs["env"]["LD_PRELOAD"] == "/lib/aarch64-linux-gnu/libgomp.so.1:libcarb.env.shim.so" + + def test_run_python_command_accepts_virtual_environment_on_bundled_python(tmp_path): """A virtual environment created on a downloaded package's Python runs that interpreter.""" local_sim = tmp_path / "_isaac_sim"