Skip to content

Build dqrobotics from a pinned submodule, statically, into _core - #10

Merged
mmmarinho merged 1 commit into
mainfrom
dqrobotics-static-submodule
Oct 1, 2026
Merged

mmmarinho merged 1 commit into
mainfrom
dqrobotics-static-submodule

Conversation

@mmmarinho

@mmmarinho mmmarinho commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

With this change, _core compiles the dqrobotics C++ library from a pinned git submodule and links it statically, the same way working-needlemanipulation does. It no longer links a system-installed libdqrobotics that the wheel repair tools then had to bundle. So the build no longer needs the DQ Robotics PPA, a dqrobotics build from source on macOS and Windows, delocate or delvewheel.

The pinned dqrobotics commit

submodules/dqrobotics_cpp is pinned to dqrobotics/cpp 674eae4d8804baca6dc22bbbe3afc3b323c05cdf ("[debian] Created docker files to test, identified causes of #73 and modified debian/rules.", 2026-04-08). This is the commit the required dqrobotics==26.4.0a7 was built from. It was found as follows:

  • dqrobotics/python versions its releases with setuptools-git-versioning, dev_template = "{tag}.a{ccount}". 26.4.0a7 is therefore the 7th commit after tag v26.04.0, which is e8f43c1 ("Fixing stubs and a few wrong py::args.", 2026-09-28).
  • The workflow run for e8f43c1 on master started at 13:04 UTC, and PyPI received 26.4.0a7 at 13:08 UTC.
  • That workflow runs git submodule update --init --recursive without --remote, so it builds the cpp submodule exactly as e8f43c1 records it: 674eae4. The two commits before it (caa197e = a6, 9282a59 = a5) record the same commit.

674eae4 already has DQ_JointType, which SerialManipulatorSimulatorFriendly needs, so no newer commit was required.

Why the pin matters: _core and the dqrobotics Python package's extension now each contain their own copy of dqrobotics. pybind11's type registry is shared between extension modules, so DQ and DQ_SerialManipulator objects pass between the two copies:

  • SerialManipulatorSimulatorFriendly is built by _core, and its inherited fkm, pose_jacobian, set_base_frame, ... run in the dqrobotics package's copy.
  • DQ arguments and results come from the dqrobotics package.

So the two copies must have identical class layouts. Keep this submodule at the cpp commit of the dqrobotics release in pyproject.toml, and when dqrobotics is raised, move both together. The requirement stays at dqrobotics>=26.4.0a7. Only dqrobotics/cpp d4fd283 (documentation only) is newer than the pin today.

Changes

  • CMakeLists.txt
    • add_subdirectory(submodules/dqrobotics_cpp EXCLUDE_FROM_ALL) with BUILD_SHARED_LIBS OFF and CMAKE_POSITION_INDEPENDENT_CODE ON.
    • dqrobotics::dqrobotics is an ALIAS of the static target, and it is defined before add_subdirectory(submodules/sas_cpp).
    • dqrobotics' PUBLIC warning flags are dropped from its interface, so they do not leak into _core.
    • MARINHO_LAB_SAS_CORE_INSTALL OFF: sas_cpp's install(EXPORT) cannot export a dependency on a non-installed target.
    • dqrobotics' CMakeLists finds Eigen with find_package(Eigen3): Homebrew via CMAKE_PREFIX_PATH, vcpkg via the toolchain, libeigen3-dev on Linux. It has no hard-coded Homebrew path at this commit.
    • Hidden visibility (CMAKE_CXX_VISIBILITY_PRESET hidden, CMAKE_VISIBILITY_INLINES_HIDDEN) for the static libraries. _core then exports only PyInit__core (checked with nm -gU), so none of its dqrobotics symbols can interpose with the copy in the dqrobotics extension. Cross-module type lookup is unaffected, because pybind11 matches types by their type-name strings.
    • Eigen include shim removed. Its comment says the dqrobotics headers include <eigen3/Eigen/Dense>, but no file of the pinned commit (or of sas_cpp, or of src/) has that include.
  • sas_cpp submodule bumped to Accept a dqrobotics::dqrobotics target from a parent project sas_cpp#12 (b25253b). That PR makes sas_cpp use a parent's dqrobotics::dqrobotics and adds MARINHO_LAB_SAS_CORE_INSTALL. The bump also brings sas_cpp main's "Remove 'using namespace Eigen' from public headers", hence the using Eigen::VectorXd; added to src/sas_robot_driver_py.cpp. After sas_cpp#12 is merged, this submodule should be moved to sas_cpp main (I can push that bump to this branch).
  • publish.yml
    • Removed: the PPA, the dqrobotics builds on macOS and Windows, and the delocate and delvewheel repairs.
    • Kept: Eigen (libeigen3-dev, brew eigen, vcpkg eigen3), auditwheel for the manylinux tag, MACOSX_DEPLOYMENT_TARGET, ARCHFLAGS, _PYTHON_HOST_PLATFORM, and the smoke test.
    • The smoke test now also checks that the inherited fkm/pose_jacobian (which run in the dqrobotics package) agree with raw_fkm/raw_pose_jacobian.
  • docker/
    • The Dockerfile no longer uses the PPA or the Eigen symlink.
    • build.sh adds interop checks: inherited fkm/pose_jacobian, set_base_frame/set_reference_frame, and DQ_Kinematics.translation_jacobian on the _core object.
    • build.sh also adds an ldd check that _core links no dqrobotics shared library.
  • README: the build instructions now need only Eigen.

Testing

  • macOS (arm64, Python 3.14, Homebrew Eigen 5.0.1):
    • python -m build --wheel, then installed in a clean venv with --pre dqrobotics (26.4.0a7).
    • The docker API check (finite-difference Jacobian and the new interop checks) and the examples pass.
    • otool -L _core*.so lists only libc++ and libSystem.
  • Ubuntu (cd docker && docker compose run --rm --build marinholab_sas_core): all checks pass, and ldd shows no libdqrobotics.
  • CI: all 20 wheel builds (Linux x86_64/aarch64, macOS arm64 and Windows; Python 3.10–3.14), including the smoke test, pass. publish is skipped on PRs.

Wheel sizes for cp314, from 26.9.11 on PyPI to this PR's CI artifacts:

Platform 26.9.11 (PyPI) This branch
manylinux x86_64 15.7 MB 298 KB
manylinux aarch64 15.5 MB 264 KB
macOS arm64 376 KB 172 KB
Windows amd64 1.09 MB 204 KB

🤖 Generated with Claude Code

Add dqrobotics/cpp as submodules/dqrobotics_cpp, pinned to 674eae4, the
commit the required dqrobotics 26.4.0a7 Python release was built from (its
cpp submodule at dqrobotics/python e8f43c1 = v26.04.0 + 7 commits). _core
links it statically with hidden visibility, as working-needlemanipulation
does; DQ and DQ_SerialManipulator objects are still the dqrobotics
package's, through pybind11's shared type registry, so the two copies must
keep the same class layouts.

sas_cpp is bumped to the branch that uses a parent's dqrobotics::dqrobotics
target (MarinhoLab/sas_cpp#12). Its headers no longer bring Eigen's names
into scope, so sas_robot_driver_py.cpp uses Eigen::VectorXd explicitly.

The workflow no longer installs the DQ Robotics PPA or builds dqrobotics on
macOS and Windows, and no longer repairs the macOS and Windows wheels with
delocate and delvewheel (auditwheel still sets the manylinux tag). The
Docker pipeline drops the PPA and checks dqrobotics interop and that _core
links no libdqrobotics. The Eigen include shim is gone: no header of the
pinned dqrobotics includes <eigen3/Eigen/Dense>.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@mmmarinho mmmarinho left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

👍

@mmmarinho
mmmarinho merged commit 649f975 into main Oct 1, 2026
25 checks passed
@mmmarinho
mmmarinho deleted the dqrobotics-static-submodule branch October 1, 2026 09:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant