cmake_minimum_required(VERSION 3.25)
if(NOT DEFINED REFORGE_CORE_VERSION OR REFORGE_CORE_VERSION STREQUAL "")
    if(DEFINED ENV{REFORGE_CORE_VERSION} AND NOT "$ENV{REFORGE_CORE_VERSION}" STREQUAL "")
        set(
            REFORGE_CORE_VERSION
            "$ENV{REFORGE_CORE_VERSION}"
            CACHE STRING
            "Reforge Core package version"
        )
    else()
        set(
            REFORGE_CORE_VERSION
            "0.0.0"
            CACHE STRING
            "Reforge Core package version"
        )
    endif()
endif()
set(
    REFORGE_CORE_VERSION
    "${REFORGE_CORE_VERSION}"
    CACHE STRING
    "Reforge Core package version"
    FORCE
)
if(NOT REFORGE_CORE_VERSION MATCHES "^[0-9]+\\.[0-9]+\\.[0-9]+$")
    message(FATAL_ERROR
        "REFORGE_CORE_VERSION must be a numeric X.Y.Z version."
    )
endif()
project(ReforgeCore VERSION "${REFORGE_CORE_VERSION}" LANGUAGES CXX)

include(CMakePackageConfigHelpers)
include(CTest)
include(GNUInstallDirs)

set(_reforge_shaper_install_bindir "${CMAKE_INSTALL_BINDIR}")
set(_reforge_shaper_install_includedir "${CMAKE_INSTALL_INCLUDEDIR}")
set(_reforge_shaper_install_libdir "${CMAKE_INSTALL_LIBDIR}")
set(_reforge_core_python_install_dir "reforge_core/control")
if(SKBUILD)
    set(_reforge_shaper_install_bindir "lib")
    set(_reforge_shaper_install_libdir "lib")
    set(_reforge_core_python_install_dir "../control")
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

option(
    REFORGE_BUILD_SHAPER
    "Build the Reforge Shaper native SDK module"
    ON
)
option(
    REFORGE_BUILD_JOINT_TRACKER
    "Build the Reforge Joint Tracker native SDK module"
    OFF
)
option(
    REFORGE_SHAPER_QUALIFY_CLARABEL
    "Build the private Clarabel qualification adapter and corpus"
    OFF
)
option(
    REFORGE_SHAPER_ENABLE_SANITIZERS
    "Instrument native targets with address and undefined-behavior sanitizers"
    OFF
)
option(
    REFORGE_SHAPER_BUILD_PYTHON_BINDINGS
    "Build the Python extension module for the native Shaper runtime"
    ON
)
option(
    REFORGE_JOINT_TRACKER_BUILD_PYTHON_BINDINGS
    "Build the Python extension module for the native Joint Tracker runtime"
    OFF
)
option(
    REFORGE_SHAPER_INSTALL_RUNTIME_DEPENDENCIES
    "Install resolved non-system shared library dependencies beside the SDK"
    OFF
)
option(
    REFORGE_SHAPER_CARGO_OFFLINE
    "Require the locked Clarabel Rust build to use only the Cargo cache"
    OFF
)
option(
    REFORGE_SHAPER_BUILD_ROS2_ADAPTER
    "Build the optional ROS 2 joint-trajectory adapter"
    OFF
)
set(
    REFORGE_SHAPER_SANITIZERS
    "address,undefined"
    CACHE STRING
    "Comma-separated Clang/GCC sanitizers enabled for native targets"
)
if(REFORGE_SHAPER_ENABLE_SANITIZERS)
    if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
        message(FATAL_ERROR
            "REFORGE_SHAPER_ENABLE_SANITIZERS requires Clang or GCC."
        )
    endif()
    add_compile_options(
        "-fsanitize=${REFORGE_SHAPER_SANITIZERS}"
        -fno-omit-frame-pointer
    )
    add_link_options("-fsanitize=${REFORGE_SHAPER_SANITIZERS}")
    # Keep Eigen's inline allocation ABI aligned with the qualified Pinocchio
    # binary when sanitizer instrumentation changes allocation assumptions.
    add_compile_definitions(EIGEN_MALLOC_ALREADY_ALIGNED=1)
endif()

function(reforge_native_keep_assertions_enabled target_name)
    if(NOT TARGET "${target_name}")
        return()
    endif()
    target_compile_options("${target_name}" PRIVATE
        "$<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>:-UNDEBUG>"
        "$<$<COMPILE_LANG_AND_ID:CXX,MSVC>:/UNDEBUG>"
    )
endfunction()

# The Clarabel adapter is private to native implementation targets. Hide its
# C++ helper/template symbols while public Joint Tracker symbols retain their
# existing visibility.
set_source_files_properties(
    src/solver/clarabel_solver.cpp
    PROPERTIES
        COMPILE_OPTIONS
            "$<$<COMPILE_LANG_AND_ID:CXX,GNU,Clang,AppleClang>:-fvisibility=hidden>"
)

function(reforge_native_materialize_clarabel_for_skbuild)
    if(NOT SKBUILD OR REFORGE_SHAPER_CLARABEL_ROOT)
        return()
    endif()

    set(
        _reforge_clarabel_wheel_deps_root
        "${CMAKE_CURRENT_BINARY_DIR}/wheel-dependencies"
    )
    execute_process(
        COMMAND
            "${CMAKE_COMMAND}"
            "-DREFORGE_SHAPER_DEPS_ROOT=${_reforge_clarabel_wheel_deps_root}"
            -P "${CMAKE_CURRENT_SOURCE_DIR}/cmake/MaterializeClarabel.cmake"
        RESULT_VARIABLE _reforge_clarabel_materialize_result
        OUTPUT_VARIABLE _reforge_clarabel_materialize_output
        ERROR_VARIABLE _reforge_clarabel_materialize_error
    )
    if(NOT _reforge_clarabel_materialize_result EQUAL 0)
        message(FATAL_ERROR
            "Failed to materialize the locked wheel solver sources:\n"
            "${_reforge_clarabel_materialize_output}"
            "${_reforge_clarabel_materialize_error}"
        )
    endif()

    find_program(_reforge_clarabel_rustc rustc REQUIRED)
    find_program(_reforge_clarabel_cargo cargo REQUIRED)
    execute_process(
        COMMAND "${_reforge_clarabel_rustc}" --version
        RESULT_VARIABLE _reforge_clarabel_rustc_result
        OUTPUT_VARIABLE _reforge_clarabel_rustc_version
        OUTPUT_STRIP_TRAILING_WHITESPACE
    )
    if(
        NOT _reforge_clarabel_rustc_result EQUAL 0
        OR NOT _reforge_clarabel_rustc_version MATCHES "^rustc 1\\.84\\.1 "
    )
        message(FATAL_ERROR
            "Native wheels require rustc 1.84.1 exactly; found "
            "'${_reforge_clarabel_rustc_version}'."
        )
    endif()

    set(
        _reforge_clarabel_wheel_root
        "${_reforge_clarabel_wheel_deps_root}/Clarabel.cpp"
    )
    set(
        _reforge_clarabel_cargo_command
        "${_reforge_clarabel_cargo}" build --release --locked
        --no-default-features
    )
    if(REFORGE_SHAPER_CARGO_OFFLINE)
        list(APPEND _reforge_clarabel_cargo_command --offline)
    endif()
    execute_process(
        COMMAND ${_reforge_clarabel_cargo_command}
        WORKING_DIRECTORY "${_reforge_clarabel_wheel_root}/rust_wrapper"
        RESULT_VARIABLE _reforge_clarabel_cargo_result
        OUTPUT_VARIABLE _reforge_clarabel_cargo_output
        ERROR_VARIABLE _reforge_clarabel_cargo_error
    )
    if(NOT _reforge_clarabel_cargo_result EQUAL 0)
        message(FATAL_ERROR
            "Failed to build the locked wheel solver with rustc 1.84.1:\n"
            "${_reforge_clarabel_cargo_output}"
            "${_reforge_clarabel_cargo_error}"
        )
    endif()
    set(
        REFORGE_SHAPER_CLARABEL_ROOT
        "${_reforge_clarabel_wheel_root}"
        CACHE PATH
        "Materialized checksum-verified Clarabel.cpp source root"
        FORCE
    )
    set(
        REFORGE_SHAPER_CLARABEL_ROOT
        "${_reforge_clarabel_wheel_root}"
        PARENT_SCOPE
    )
endfunction()

set(
    REFORGE_SHAPER_CLARABEL_ROOT
    ""
    CACHE PATH
    "Materialized checksum-verified Clarabel.cpp source root"
)
set(
    REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
    ""
    CACHE PATH
    "nlohmann_json include directory fallback when no CMake package exists"
)
set(
    REFORGE_NLOHMANN_JSON_INCLUDE_DIR
    ""
    CACHE PATH
    "nlohmann_json include directory fallback for native module builds"
)
set(
    REFORGE_SHAPER_NLOHMANN_INCLUDE_DIR
    ""
    CACHE PATH
    "Compatibility alias for the nlohmann_json include directory fallback"
)
set(
    REFORGE_SHAPER_INSTALL_RPATH
    "$ORIGIN"
    CACHE STRING
    "Installed runtime search path for Reforge Shaper shared libraries"
)
set(
    REFORGE_SHAPER_RUNTIME_DEPENDENCY_INSTALL_SUBDIR
    ""
    CACHE STRING
    "Optional subdirectory under CMAKE_INSTALL_LIBDIR for copied runtime dependencies"
)

if(
    REFORGE_SHAPER_NLOHMANN_INCLUDE_DIR
    AND REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
    AND NOT REFORGE_SHAPER_NLOHMANN_INCLUDE_DIR STREQUAL
        REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
)
    message(FATAL_ERROR
        "REFORGE_SHAPER_NLOHMANN_INCLUDE_DIR and "
        "REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR both set different paths."
    )
endif()
if(
    REFORGE_SHAPER_NLOHMANN_INCLUDE_DIR
    AND NOT REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
)
    set(
        REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
        "${REFORGE_SHAPER_NLOHMANN_INCLUDE_DIR}"
    )
endif()
if(
    REFORGE_NLOHMANN_JSON_INCLUDE_DIR
    AND REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
    AND NOT REFORGE_NLOHMANN_JSON_INCLUDE_DIR STREQUAL
        REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
)
    message(FATAL_ERROR
        "REFORGE_NLOHMANN_JSON_INCLUDE_DIR and "
        "REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR both set different paths."
    )
endif()
if(
    REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR
    AND NOT REFORGE_NLOHMANN_JSON_INCLUDE_DIR
)
    set(
        REFORGE_NLOHMANN_JSON_INCLUDE_DIR
        "${REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR}"
    )
endif()

if(REFORGE_BUILD_SHAPER)

reforge_native_materialize_clarabel_for_skbuild()

find_package(Eigen3 REQUIRED NO_MODULE)
find_package(nlohmann_json 3.12.0 EXACT CONFIG QUIET)

function(reforge_native_ensure_urdfdom_headers_target)
    find_package(urdfdom_headers QUIET)
    if(NOT urdfdom_headers_FOUND OR TARGET urdfdom_headers::urdfdom_headers)
        return()
    endif()

    set(_reforge_urdfdom_headers_include_dirs "")
    if(DEFINED urdfdom_headers_INCLUDE_DIRS)
        set(_reforge_urdfdom_headers_include_dirs
            "${urdfdom_headers_INCLUDE_DIRS}")
    elseif(DEFINED urdfdom_headers_INCLUDE_DIR)
        set(_reforge_urdfdom_headers_include_dirs
            "${urdfdom_headers_INCLUDE_DIR}")
    endif()

    add_library(urdfdom_headers::urdfdom_headers INTERFACE IMPORTED)
    if(_reforge_urdfdom_headers_include_dirs)
        set_target_properties(urdfdom_headers::urdfdom_headers PROPERTIES
            INTERFACE_INCLUDE_DIRECTORIES
            "${_reforge_urdfdom_headers_include_dirs}"
        )
    endif()
endfunction()

reforge_native_ensure_urdfdom_headers_target()
find_package(pinocchio 4 CONFIG REQUIRED)
if(REFORGE_SHAPER_BUILD_PYTHON_BINDINGS)
    set(PYBIND11_FINDPYTHON ON)
    find_package(pybind11 CONFIG QUIET)
endif()

if(NOT TARGET nlohmann_json::nlohmann_json)
    if(REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR)
        set(_reforge_nlohmann_include_dir
            "${REFORGE_SHAPER_NLOHMANN_JSON_INCLUDE_DIR}")
        set(_reforge_nlohmann_abi_header
            "${_reforge_nlohmann_include_dir}/nlohmann/detail/abi_macros.hpp")
        if(
            EXISTS "${_reforge_nlohmann_include_dir}/nlohmann/json.hpp"
            AND EXISTS "${_reforge_nlohmann_abi_header}"
        )
            file(
                STRINGS "${_reforge_nlohmann_abi_header}"
                _reforge_nlohmann_major_line
                REGEX "^[ \t]*#define[ \t]+NLOHMANN_JSON_VERSION_MAJOR[ \t]+[0-9]+"
            )
            file(
                STRINGS "${_reforge_nlohmann_abi_header}"
                _reforge_nlohmann_minor_line
                REGEX "^[ \t]*#define[ \t]+NLOHMANN_JSON_VERSION_MINOR[ \t]+[0-9]+"
            )
            file(
                STRINGS "${_reforge_nlohmann_abi_header}"
                _reforge_nlohmann_patch_line
                REGEX "^[ \t]*#define[ \t]+NLOHMANN_JSON_VERSION_PATCH[ \t]+[0-9]+"
            )
            string(
                REGEX REPLACE
                ".*NLOHMANN_JSON_VERSION_MAJOR[ \t]+([0-9]+).*"
                "\\1"
                _reforge_nlohmann_major
                "${_reforge_nlohmann_major_line}"
            )
            string(
                REGEX REPLACE
                ".*NLOHMANN_JSON_VERSION_MINOR[ \t]+([0-9]+).*"
                "\\1"
                _reforge_nlohmann_minor
                "${_reforge_nlohmann_minor_line}"
            )
            string(
                REGEX REPLACE
                ".*NLOHMANN_JSON_VERSION_PATCH[ \t]+([0-9]+).*"
                "\\1"
                _reforge_nlohmann_patch
                "${_reforge_nlohmann_patch_line}"
            )
            set(_reforge_nlohmann_version
                "${_reforge_nlohmann_major}.${_reforge_nlohmann_minor}.${_reforge_nlohmann_patch}")
        endif()
    endif()

    if(NOT _reforge_nlohmann_version STREQUAL "3.12.0")
        find_package(Python3 COMPONENTS Interpreter QUIET)
    endif()
    if(
        NOT _reforge_nlohmann_version STREQUAL "3.12.0"
        AND Python3_Interpreter_FOUND
    )
        execute_process(
            COMMAND
                "${Python3_EXECUTABLE}" -c
                "from importlib.metadata import version; import nlohmann_json; print(version('nlohmann-json')); print(nlohmann_json.get_include())"
            RESULT_VARIABLE _reforge_nlohmann_result
            OUTPUT_VARIABLE _reforge_nlohmann_output
            ERROR_QUIET
            OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        if(_reforge_nlohmann_result EQUAL 0)
            string(REPLACE "\n" ";" _reforge_nlohmann_values
                "${_reforge_nlohmann_output}")
            list(LENGTH _reforge_nlohmann_values
                _reforge_nlohmann_value_count)
            if(_reforge_nlohmann_value_count EQUAL 2)
                list(GET _reforge_nlohmann_values 0
                    _reforge_nlohmann_version)
                list(GET _reforge_nlohmann_values 1
                    _reforge_nlohmann_include_dir)
            endif()
        endif()
    endif()

    if(
        NOT _reforge_nlohmann_version STREQUAL "3.12.0"
        OR NOT EXISTS "${_reforge_nlohmann_include_dir}/nlohmann/json.hpp"
    )
        message(FATAL_ERROR
            "nlohmann_json 3.12.0 is required. Install a discoverable CMake "
            "package or the pinned nlohmann-json Python build dependency."
        )
    endif()

    add_library(nlohmann_json::nlohmann_json INTERFACE IMPORTED)
    set_target_properties(nlohmann_json::nlohmann_json PROPERTIES
        INTERFACE_INCLUDE_DIRECTORIES "${_reforge_nlohmann_include_dir}"
    )
endif()

set(_reforge_shaper_generated_include_dir
    "${CMAKE_CURRENT_BINARY_DIR}/generated/include")
configure_file(
    include/reforge_core/native/common/export.hpp.in
    "${_reforge_shaper_generated_include_dir}/reforge_core/native/common/export.hpp"
    @ONLY
)

add_library(reforge_shaper_common
    src/control/shaper/modal_inference_strategy.cpp
    src/control/shaper/residual_switch_config.cpp
)
add_library(ReforgeShaper::common ALIAS reforge_shaper_common)

set_target_properties(reforge_shaper_common PROPERTIES
    EXPORT_NAME common
    POSITION_INDEPENDENT_CODE ON
)
target_compile_features(reforge_shaper_common PUBLIC cxx_std_17)
target_compile_definitions(reforge_shaper_common
    PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
)
if(NOT BUILD_SHARED_LIBS)
    target_compile_definitions(
        reforge_shaper_common PUBLIC REFORGE_SHAPER_STATIC_DEFINE
    )
endif()
target_include_directories(reforge_shaper_common
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
        "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
)
target_link_libraries(reforge_shaper_common PUBLIC Eigen3::Eigen)

add_library(reforge_shaper_trajectory
    src/control/shaper/shaper_window_helpers.cpp
    src/util/interpolation.cpp
    src/util/timing/joint_limits.cpp
    src/util/timing/joint_trajectory.cpp
    src/util/timing/resampling.cpp
)
add_library(ReforgeShaper::trajectory ALIAS reforge_shaper_trajectory)

set_target_properties(reforge_shaper_trajectory PROPERTIES
    EXPORT_NAME trajectory
    POSITION_INDEPENDENT_CODE ON
)
target_compile_features(reforge_shaper_trajectory PUBLIC cxx_std_17)
target_compile_definitions(reforge_shaper_trajectory
    PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
)
if(NOT BUILD_SHARED_LIBS)
    target_compile_definitions(
        reforge_shaper_trajectory PUBLIC REFORGE_SHAPER_STATIC_DEFINE
    )
endif()
target_include_directories(reforge_shaper_trajectory
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
        "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
)
target_link_libraries(
    reforge_shaper_trajectory PUBLIC ReforgeShaper::common
)

add_library(reforge_shaper_model
    src/control/model/map_loader.cpp
    src/control/model/model_types.cpp
)
add_library(ReforgeShaper::model ALIAS reforge_shaper_model)

set_target_properties(reforge_shaper_model PROPERTIES
    EXPORT_NAME model
    POSITION_INDEPENDENT_CODE ON
)
target_compile_features(reforge_shaper_model PUBLIC cxx_std_17)
target_compile_definitions(reforge_shaper_model
    PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
)
if(NOT BUILD_SHARED_LIBS)
    target_compile_definitions(
        reforge_shaper_model PUBLIC REFORGE_SHAPER_STATIC_DEFINE
    )
endif()
target_include_directories(reforge_shaper_model
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
        "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
)
target_link_libraries(reforge_shaper_model PUBLIC ReforgeShaper::common)
target_link_libraries(
    reforge_shaper_model
    PRIVATE "$<BUILD_INTERFACE:nlohmann_json::nlohmann_json>"
)

add_library(reforge_shaper_runtime
    src/control/runtime/base_shaper.cpp
    src/control/runtime/modal_inference.cpp
    src/control/runtime/task_space.cpp
    src/control/runtime/weighting.cpp
)
add_library(ReforgeShaper::runtime ALIAS reforge_shaper_runtime)

set_target_properties(reforge_shaper_runtime PROPERTIES
    EXPORT_NAME runtime
    POSITION_INDEPENDENT_CODE ON
)
target_compile_features(reforge_shaper_runtime PUBLIC cxx_std_17)
target_compile_definitions(reforge_shaper_runtime
    PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
)
if(NOT BUILD_SHARED_LIBS)
    target_compile_definitions(
        reforge_shaper_runtime PUBLIC REFORGE_SHAPER_STATIC_DEFINE
    )
endif()
target_include_directories(reforge_shaper_runtime
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
        "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
)
target_link_libraries(
    reforge_shaper_runtime PUBLIC ReforgeShaper::common
)

add_library(reforge_shaper_window
    src/control/window/windowed_buffer.cpp
    src/control/window/shaper_window_handle.cpp
)
add_library(ReforgeShaper::window ALIAS reforge_shaper_window)

set_target_properties(reforge_shaper_window PROPERTIES
    EXPORT_NAME window
    POSITION_INDEPENDENT_CODE ON
)
target_compile_features(reforge_shaper_window PUBLIC cxx_std_17)
target_compile_definitions(reforge_shaper_window
    PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
)
if(NOT BUILD_SHARED_LIBS)
    target_compile_definitions(
        reforge_shaper_window PUBLIC REFORGE_SHAPER_STATIC_DEFINE
    )
endif()
target_include_directories(reforge_shaper_window
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
        "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
)
target_link_libraries(
    reforge_shaper_window
    PUBLIC ReforgeShaper::common ReforgeShaper::trajectory
)

add_library(reforge_shaper_dynamics
    src/util/robot_dynamics.cpp
)
add_library(ReforgeShaper::dynamics ALIAS reforge_shaper_dynamics)

set_target_properties(reforge_shaper_dynamics PROPERTIES
    EXPORT_NAME dynamics
    POSITION_INDEPENDENT_CODE ON
)
target_compile_features(reforge_shaper_dynamics PUBLIC cxx_std_17)
target_compile_definitions(reforge_shaper_dynamics
    PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
)
if(NOT BUILD_SHARED_LIBS)
    target_compile_definitions(
        reforge_shaper_dynamics PUBLIC REFORGE_SHAPER_STATIC_DEFINE
    )
endif()
target_include_directories(reforge_shaper_dynamics
    PUBLIC
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
        "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
)
target_link_libraries(
    reforge_shaper_dynamics
    PUBLIC ReforgeShaper::common
    PRIVATE pinocchio::pinocchio
)
target_link_libraries(
    reforge_shaper_runtime
    PRIVATE
        ReforgeShaper::dynamics
        ReforgeShaper::model
        ReforgeShaper::trajectory
)

if(REFORGE_SHAPER_QUALIFY_CLARABEL AND NOT REFORGE_SHAPER_CLARABEL_ROOT)
    message(FATAL_ERROR
        "REFORGE_SHAPER_QUALIFY_CLARABEL requires "
        "REFORGE_SHAPER_CLARABEL_ROOT."
    )
endif()

if(REFORGE_SHAPER_CLARABEL_ROOT)
    if(NOT IS_DIRECTORY "${REFORGE_SHAPER_CLARABEL_ROOT}/include")
        message(FATAL_ERROR
            "REFORGE_SHAPER_CLARABEL_ROOT must name the locked "
            "Clarabel.cpp source root."
        )
    endif()
    set(
        _reforge_clarabel_static_library
        "${REFORGE_SHAPER_CLARABEL_ROOT}/rust_wrapper/target/release/libclarabel_c.a"
    )
    if(NOT EXISTS "${_reforge_clarabel_static_library}")
        message(FATAL_ERROR
            "The locked Clarabel static library is missing: "
            "${_reforge_clarabel_static_library}"
        )
    endif()

    add_library(reforge_clarabel_c_static STATIC IMPORTED GLOBAL)
    set_target_properties(reforge_clarabel_c_static PROPERTIES
        IMPORTED_LOCATION "${_reforge_clarabel_static_library}"
        INTERFACE_INCLUDE_DIRECTORIES
            "${REFORGE_SHAPER_CLARABEL_ROOT}/include"
        INTERFACE_LINK_OPTIONS
            "$<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,libclarabel_c.a>"
    )

    add_library(reforge_shaper_solver
        src/control/shaper/modal_switch_optimizer.cpp
        src/solver/clarabel_solver.cpp
        src/util/trajopt/traj_qp.cpp
    )
    add_library(ReforgeShaper::solver ALIAS reforge_shaper_solver)
    set_target_properties(reforge_shaper_solver PROPERTIES
        EXPORT_NAME solver
        POSITION_INDEPENDENT_CODE ON
    )
    target_compile_features(reforge_shaper_solver PUBLIC cxx_std_17)
    target_compile_definitions(
        reforge_shaper_solver PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
    )
    if(NOT BUILD_SHARED_LIBS)
        target_compile_definitions(
            reforge_shaper_solver PUBLIC REFORGE_SHAPER_STATIC_DEFINE
        )
    endif()
    target_include_directories(reforge_shaper_solver
        PUBLIC
            "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
            "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
            "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
        PRIVATE
            "${CMAKE_CURRENT_SOURCE_DIR}/src"
            "${REFORGE_SHAPER_CLARABEL_ROOT}/include"
    )
    target_link_libraries(
        reforge_shaper_solver
        PUBLIC ReforgeShaper::trajectory
        PRIVATE reforge_clarabel_c_static
    )
    target_sources(
        reforge_shaper_runtime PRIVATE
            src/control/shaper/residual_alignment.cpp
            src/control/shaper/residual_switch.cpp
            src/control/shaper/windowing.cpp
    )
    target_link_libraries(
        reforge_shaper_runtime PUBLIC
            ReforgeShaper::solver
            ReforgeShaper::trajectory
            ReforgeShaper::window
    )

    add_library(reforge_shaper_backend
        src/control/shaper/backend/native_shaper.cpp
    )
    add_library(ReforgeShaper::backend ALIAS reforge_shaper_backend)
    set_target_properties(reforge_shaper_backend PROPERTIES
        EXPORT_NAME backend
        POSITION_INDEPENDENT_CODE ON
    )
    target_compile_features(reforge_shaper_backend PUBLIC cxx_std_17)
    target_compile_definitions(
        reforge_shaper_backend PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
    )
    if(NOT BUILD_SHARED_LIBS)
        target_compile_definitions(
            reforge_shaper_backend PUBLIC REFORGE_SHAPER_STATIC_DEFINE
        )
    endif()
    target_include_directories(reforge_shaper_backend
        PUBLIC
            "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
            "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
            "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
    )
    target_link_libraries(
        reforge_shaper_backend
        PUBLIC
            ReforgeShaper::common
            ReforgeShaper::dynamics
            ReforgeShaper::model
            ReforgeShaper::runtime
            ReforgeShaper::solver
            ReforgeShaper::trajectory
            ReforgeShaper::window
    )
endif()

if(REFORGE_SHAPER_BUILD_ROS2_ADAPTER)
    if(NOT TARGET reforge_shaper_backend)
        message(FATAL_ERROR
            "REFORGE_SHAPER_BUILD_ROS2_ADAPTER requires the complete native "
            "backend and REFORGE_SHAPER_CLARABEL_ROOT."
        )
    endif()
    find_package(builtin_interfaces CONFIG REQUIRED)
    find_package(trajectory_msgs CONFIG REQUIRED)

    add_library(reforge_shaper_ros2
        src/control/shaper/ros2/joint_trajectory_adapter.cpp
    )
    add_library(ReforgeShaper::ros2 ALIAS reforge_shaper_ros2)
    set_target_properties(reforge_shaper_ros2 PROPERTIES
        EXPORT_NAME ros2
        POSITION_INDEPENDENT_CODE ON
    )
    target_compile_features(reforge_shaper_ros2 PUBLIC cxx_std_17)
    target_compile_definitions(
        reforge_shaper_ros2 PRIVATE REFORGE_SHAPER_COMMON_EXPORTS
    )
    if(NOT BUILD_SHARED_LIBS)
        target_compile_definitions(
            reforge_shaper_ros2 PUBLIC REFORGE_SHAPER_STATIC_DEFINE
        )
    endif()
    target_include_directories(reforge_shaper_ros2
        PUBLIC
            "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
            "$<BUILD_INTERFACE:${_reforge_shaper_generated_include_dir}>"
            "$<INSTALL_INTERFACE:${_reforge_shaper_install_includedir}>"
    )
    target_link_libraries(reforge_shaper_ros2
        PUBLIC
            ReforgeShaper::backend
            builtin_interfaces::builtin_interfaces__rosidl_generator_cpp
            trajectory_msgs::trajectory_msgs__rosidl_generator_cpp
    )
endif()

if(REFORGE_SHAPER_QUALIFY_CLARABEL)
    add_library(reforge_shaper_clarabel_qualification STATIC
        src/solver/clarabel_qualification_adapter.cpp
    )
    set_target_properties(
        reforge_shaper_clarabel_qualification
        PROPERTIES POSITION_INDEPENDENT_CODE ON
    )
    target_compile_features(
        reforge_shaper_clarabel_qualification PRIVATE cxx_std_17
    )
    target_include_directories(
        reforge_shaper_clarabel_qualification
        PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src"
    )
    target_link_libraries(
        reforge_shaper_clarabel_qualification
        PUBLIC Eigen3::Eigen
        PRIVATE ReforgeShaper::solver
    )
endif()

if(REFORGE_SHAPER_BUILD_PYTHON_BINDINGS AND pybind11_FOUND)
    pybind11_add_module(_native_shaper NO_EXTRAS
        bindings/python/reforge_core/control/native_shaper_module.cpp
        bindings/python/reforge_core/control/bind_base_shaper.cpp
        bindings/python/reforge_core/control/bind_runtime_services.cpp
        bindings/python/reforge_core/control/bind_map_loader.cpp
        bindings/python/reforge_core/control/bind_model_types.cpp
        bindings/python/reforge_core/control/bind_shaper_foundation.cpp
        bindings/python/reforge_core/control/bind_windowed_buffer.cpp
        bindings/python/reforge_core/util/bind_interpolation.cpp
        bindings/python/reforge_core/util/bind_robot_dynamics.cpp
        bindings/python/reforge_core/util/timing/bind_timing.cpp
    )
    target_compile_features(_native_shaper PRIVATE cxx_std_17)
    set_target_properties(
        _native_shaper PROPERTIES INSTALL_RPATH_USE_LINK_PATH ON
    )
    target_include_directories(
        _native_shaper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/bindings/python"
    )
    target_link_libraries(
        _native_shaper
        PRIVATE
            ReforgeShaper::dynamics
            ReforgeShaper::model
            ReforgeShaper::runtime
            ReforgeShaper::trajectory
            ReforgeShaper::window
    )
    if(TARGET reforge_shaper_solver)
        target_sources(
            _native_shaper PRIVATE
                bindings/python/reforge_core/control/bind_residual.cpp
                bindings/python/reforge_core/control/bind_solver.cpp
        )
        target_compile_definitions(
            _native_shaper PRIVATE REFORGE_SHAPER_SOLVER_AVAILABLE
        )
        target_link_libraries(_native_shaper PRIVATE ReforgeShaper::solver)
    endif()
    if(TARGET reforge_shaper_backend)
        target_sources(
            _native_shaper PRIVATE
                bindings/python/reforge_core/control/bind_native_backend.cpp
        )
        target_compile_definitions(
            _native_shaper PRIVATE REFORGE_SHAPER_BACKEND_AVAILABLE
        )
        target_link_libraries(
            _native_shaper PRIVATE ReforgeShaper::backend
        )
    endif()
    if(REFORGE_SHAPER_QUALIFY_CLARABEL)
        target_compile_definitions(
            _native_shaper PRIVATE REFORGE_SHAPER_CLARABEL_QUALIFICATION
        )
        target_include_directories(
            _native_shaper PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src"
        )
        target_link_libraries(
            _native_shaper PRIVATE reforge_shaper_clarabel_qualification
        )
    endif()
    install(TARGETS _native_shaper
        LIBRARY DESTINATION "${_reforge_core_python_install_dir}"
        RUNTIME DESTINATION "${_reforge_core_python_install_dir}"
    )
    set(_reforge_shaper_complete_backend_available "false")
    if(TARGET reforge_shaper_backend)
        set(_reforge_shaper_complete_backend_available "true")
    endif()
    configure_file(
        qualification/native_build_manifest.json.in
        "${CMAKE_CURRENT_BINARY_DIR}/native_build_manifest.json"
        @ONLY
    )
    install(
        FILES
            "${CMAKE_CURRENT_BINARY_DIR}/native_build_manifest.json"
            qualification/THIRD_PARTY_NOTICES.txt
        DESTINATION "${_reforge_core_python_install_dir}/native"
    )
endif()

if(BUILD_TESTING)
    find_package(Threads REQUIRED)

    add_executable(
        reforge_shaper_common_tests
        tests/control/shaper/test_foundation.cpp
    )
    target_compile_features(reforge_shaper_common_tests PRIVATE cxx_std_17)
    target_link_libraries(
        reforge_shaper_common_tests PRIVATE ReforgeShaper::common
    )
    add_test(
        NAME reforge_shaper_common_tests
        COMMAND reforge_shaper_common_tests
    )

    add_executable(
        reforge_shaper_common_header_independence
        tests/native/header_independence.cpp
    )
    target_compile_features(
        reforge_shaper_common_header_independence PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_common_header_independence
        PRIVATE
            ReforgeShaper::dynamics
            ReforgeShaper::model
            ReforgeShaper::runtime
            ReforgeShaper::trajectory
            ReforgeShaper::window
    )
    if(TARGET reforge_shaper_backend)
        target_link_libraries(
            reforge_shaper_common_header_independence
            PRIVATE ReforgeShaper::backend
        )
    endif()
    add_test(
        NAME reforge_shaper_common_header_independence
        COMMAND reforge_shaper_common_header_independence
    )

    add_executable(
        reforge_shaper_trajectory_tests
        tests/util/test_trajectory_foundation.cpp
    )
    target_compile_features(
        reforge_shaper_trajectory_tests PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_trajectory_tests
        PRIVATE ReforgeShaper::trajectory
    )
    add_test(
        NAME reforge_shaper_trajectory_tests
        COMMAND reforge_shaper_trajectory_tests
    )

    add_executable(
        reforge_shaper_model_tests
        tests/control/model/test_model_types.cpp
    )
    target_compile_features(
        reforge_shaper_model_tests PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_model_tests PRIVATE ReforgeShaper::model
    )
    add_test(
        NAME reforge_shaper_model_tests
        COMMAND reforge_shaper_model_tests
    )

    add_executable(
        reforge_shaper_map_loader_tests
        tests/control/model/test_map_loader.cpp
    )
    target_compile_features(
        reforge_shaper_map_loader_tests PRIVATE cxx_std_17
    )
    target_compile_definitions(
        reforge_shaper_map_loader_tests
        PRIVATE
            REFORGE_MODEL_FIXTURE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/models"
    )
    target_link_libraries(
        reforge_shaper_map_loader_tests PRIVATE ReforgeShaper::model
    )
    add_test(
        NAME reforge_shaper_map_loader_tests
        COMMAND reforge_shaper_map_loader_tests
    )

    add_executable(
        reforge_shaper_runtime_tests
        tests/control/runtime/test_base_shaper.cpp
    )
    target_compile_features(
        reforge_shaper_runtime_tests PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_runtime_tests PRIVATE ReforgeShaper::runtime
    )
    add_test(
        NAME reforge_shaper_runtime_tests
        COMMAND reforge_shaper_runtime_tests
    )

    add_executable(
        reforge_shaper_runtime_service_tests
        tests/control/runtime/test_runtime_services.cpp
    )
    target_compile_features(
        reforge_shaper_runtime_service_tests PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_runtime_service_tests
        PRIVATE
            ReforgeShaper::runtime
            ReforgeShaper::dynamics
            ReforgeShaper::model
    )
    add_test(
        NAME reforge_shaper_runtime_service_tests
        COMMAND reforge_shaper_runtime_service_tests
    )

    add_executable(
        reforge_shaper_task_space_tests
        tests/control/runtime/test_task_space.cpp
    )
    target_compile_features(
        reforge_shaper_task_space_tests PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_task_space_tests
        PRIVATE ReforgeShaper::runtime ReforgeShaper::dynamics
    )
    add_test(
        NAME reforge_shaper_task_space_tests
        COMMAND reforge_shaper_task_space_tests
    )

    add_executable(
        reforge_shaper_window_tests
        tests/control/window/test_windowed_buffer.cpp
    )
    target_compile_features(
        reforge_shaper_window_tests PRIVATE cxx_std_17
    )
    target_link_libraries(
        reforge_shaper_window_tests
        PRIVATE ReforgeShaper::window Threads::Threads
    )
    add_test(
        NAME reforge_shaper_window_tests
        COMMAND reforge_shaper_window_tests
    )

    add_executable(
        reforge_shaper_dynamics_tests
        tests/util/test_robot_dynamics.cpp
    )
    target_compile_features(
        reforge_shaper_dynamics_tests PRIVATE cxx_std_17
    )
    target_compile_definitions(
        reforge_shaper_dynamics_tests
        PRIVATE
            REFORGE_DYNAMICS_FIXTURE_DIR="${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/urdf"
    )
    target_link_libraries(
        reforge_shaper_dynamics_tests
        PRIVATE ReforgeShaper::dynamics Threads::Threads
    )
    add_test(
        NAME reforge_shaper_dynamics_tests
        COMMAND reforge_shaper_dynamics_tests
    )

    if(REFORGE_SHAPER_QUALIFY_CLARABEL)
        add_executable(
            reforge_shaper_clarabel_qualification_tests
            tests/solver/test_clarabel_qualification.cpp
        )
        target_compile_features(
            reforge_shaper_clarabel_qualification_tests PRIVATE cxx_std_17
        )
        target_include_directories(
            reforge_shaper_clarabel_qualification_tests
            PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src"
        )
        target_link_libraries(
            reforge_shaper_clarabel_qualification_tests
            PRIVATE reforge_shaper_clarabel_qualification
        )
        add_test(
            NAME reforge_shaper_clarabel_qualification_tests
            COMMAND reforge_shaper_clarabel_qualification_tests
        )

        add_executable(
            reforge_shaper_clarabel_data_update_qualification_tests
            tests/solver/test_clarabel_data_update_qualification.cpp
        )
        target_compile_features(
            reforge_shaper_clarabel_data_update_qualification_tests
            PRIVATE cxx_std_17
        )
        target_include_directories(
            reforge_shaper_clarabel_data_update_qualification_tests
            PRIVATE "${REFORGE_SHAPER_CLARABEL_ROOT}/include"
        )
        target_link_libraries(
            reforge_shaper_clarabel_data_update_qualification_tests
            PRIVATE reforge_clarabel_c_static
        )
        add_test(
            NAME reforge_shaper_clarabel_data_update_qualification_tests
            COMMAND reforge_shaper_clarabel_data_update_qualification_tests
        )
    endif()
    if(TARGET reforge_shaper_backend)
        add_executable(
            reforge_shaper_backend_tests
            tests/control/shaper/backend/test_native_shaper.cpp
        )
        target_compile_features(
            reforge_shaper_backend_tests PRIVATE cxx_std_17
        )
        target_link_libraries(
            reforge_shaper_backend_tests PRIVATE ReforgeShaper::backend
        )
        add_test(
            NAME reforge_shaper_backend_tests
            COMMAND reforge_shaper_backend_tests
        )
        add_executable(
            reforge_shaper_backend_complete_tests
            tests/control/shaper/backend/test_native_shaper_complete.cpp
        )
        target_compile_features(
            reforge_shaper_backend_complete_tests PRIVATE cxx_std_17
        )
        target_link_libraries(
            reforge_shaper_backend_complete_tests
            PRIVATE ReforgeShaper::backend
        )
        add_test(
            NAME reforge_shaper_backend_complete_tests
            COMMAND reforge_shaper_backend_complete_tests
        )
        add_executable(
            reforge_shaper_backend_task_space_tests
            tests/control/shaper/backend/test_native_shaper_task_space.cpp
        )
        target_compile_features(
            reforge_shaper_backend_task_space_tests PRIVATE cxx_std_17
        )
        target_link_libraries(
            reforge_shaper_backend_task_space_tests
            PRIVATE ReforgeShaper::backend
        )
        add_test(
            NAME reforge_shaper_backend_task_space_tests
            COMMAND reforge_shaper_backend_task_space_tests
        )
    endif()
    if(TARGET reforge_shaper_ros2)
        add_executable(
            reforge_shaper_ros2_tests
            tests/control/shaper/ros2/test_joint_trajectory_adapter.cpp
        )
        target_compile_features(
            reforge_shaper_ros2_tests PRIVATE cxx_std_17
        )
        target_link_libraries(
            reforge_shaper_ros2_tests PRIVATE ReforgeShaper::ros2
        )
        add_test(
            NAME reforge_shaper_ros2_tests
            COMMAND reforge_shaper_ros2_tests
        )
    endif()
    if(TARGET reforge_shaper_solver)
        add_executable(
            reforge_shaper_solver_tests
            tests/util/trajopt/test_traj_qp.cpp
        )
        target_compile_features(
            reforge_shaper_solver_tests PRIVATE cxx_std_17
        )
        target_include_directories(
            reforge_shaper_solver_tests PRIVATE
                "${CMAKE_CURRENT_SOURCE_DIR}/src"
        )
        target_link_libraries(
            reforge_shaper_solver_tests PRIVATE ReforgeShaper::solver
        )
        add_test(
            NAME reforge_shaper_solver_tests
            COMMAND reforge_shaper_solver_tests
        )
        add_executable(
            reforge_shaper_residual_tests
            tests/control/runtime/test_residual.cpp
        )
        target_compile_features(
            reforge_shaper_residual_tests PRIVATE cxx_std_17
        )
        target_link_libraries(
            reforge_shaper_residual_tests
            PRIVATE ReforgeShaper::runtime
        )
        add_test(
            NAME reforge_shaper_residual_tests
            COMMAND reforge_shaper_residual_tests
        )
        add_executable(
            reforge_shaper_windowing_tests
            tests/control/runtime/test_windowing.cpp
        )
        target_compile_features(
            reforge_shaper_windowing_tests PRIVATE cxx_std_17
        )
        target_link_libraries(
            reforge_shaper_windowing_tests PRIVATE ReforgeShaper::runtime
        )
        add_test(
            NAME reforge_shaper_windowing_tests
            COMMAND reforge_shaper_windowing_tests
        )
    endif()
    foreach(_reforge_shaper_test_target IN ITEMS
            reforge_shaper_common_tests
            reforge_shaper_common_header_independence
            reforge_shaper_trajectory_tests
            reforge_shaper_model_tests
            reforge_shaper_map_loader_tests
            reforge_shaper_runtime_tests
            reforge_shaper_runtime_service_tests
            reforge_shaper_task_space_tests
            reforge_shaper_window_tests
            reforge_shaper_dynamics_tests
            reforge_shaper_clarabel_qualification_tests
            reforge_shaper_clarabel_data_update_qualification_tests
            reforge_shaper_backend_tests
            reforge_shaper_backend_task_space_tests
            reforge_shaper_ros2_tests
            reforge_shaper_solver_tests
            reforge_shaper_residual_tests
            reforge_shaper_windowing_tests
    )
        reforge_native_keep_assertions_enabled(
            "${_reforge_shaper_test_target}")
    endforeach()
endif()

if(TARGET reforge_shaper_common)
    if(
        NOT SKBUILD
        AND REFORGE_SHAPER_INSTALL_RUNTIME_DEPENDENCIES
        AND NOT BUILD_SHARED_LIBS
    )
        message(FATAL_ERROR
            "REFORGE_SHAPER_INSTALL_RUNTIME_DEPENDENCIES requires "
            "BUILD_SHARED_LIBS=ON so private dependencies can remain behind "
            "the installed SDK shared-library boundary."
        )
    endif()

    set(_reforge_shaper_install_targets
        reforge_shaper_common
        reforge_shaper_trajectory
        reforge_shaper_model
        reforge_shaper_dynamics
        reforge_shaper_runtime
        reforge_shaper_window
    )
    if(TARGET reforge_shaper_solver)
        list(APPEND _reforge_shaper_install_targets reforge_shaper_solver)
    endif()
    if(TARGET reforge_shaper_backend)
        list(APPEND _reforge_shaper_install_targets reforge_shaper_backend)
    endif()
    if(SKBUILD)
        if(APPLE)
            set(_reforge_shaper_sdk_install_rpath "@loader_path")
            set(
                _reforge_shaper_extension_install_rpath
                "@loader_path/../cpp/lib"
            )
        elseif(UNIX)
            set(_reforge_shaper_sdk_install_rpath "$ORIGIN")
            set(
                _reforge_shaper_extension_install_rpath
                "$ORIGIN/../cpp/lib"
            )
        endif()
        if(DEFINED _reforge_shaper_sdk_install_rpath)
            set_target_properties(
                ${_reforge_shaper_install_targets}
                PROPERTIES
                    INSTALL_RPATH "${_reforge_shaper_sdk_install_rpath}"
                    INSTALL_RPATH_USE_LINK_PATH OFF
            )
            if(TARGET _native_shaper)
                set_target_properties(
                    _native_shaper
                    PROPERTIES
                        INSTALL_RPATH
                            "${_reforge_shaper_extension_install_rpath}"
                        INSTALL_RPATH_USE_LINK_PATH OFF
                )
            endif()
        endif()
    elseif(BUILD_SHARED_LIBS)
        set_target_properties(
            ${_reforge_shaper_install_targets}
            PROPERTIES INSTALL_RPATH "${REFORGE_SHAPER_INSTALL_RPATH}"
        )
    endif()

    set(_reforge_shaper_runtime_dependency_set_args)
    if(NOT SKBUILD AND REFORGE_SHAPER_INSTALL_RUNTIME_DEPENDENCIES)
        set(
            _reforge_shaper_runtime_dependency_set_args
            RUNTIME_DEPENDENCY_SET ReforgeShaperRuntimeDependencies
        )
    endif()
    install(
        TARGETS ${_reforge_shaper_install_targets}
        EXPORT ReforgeShaperTargets
        ${_reforge_shaper_runtime_dependency_set_args}
        ARCHIVE DESTINATION "${_reforge_shaper_install_libdir}"
        LIBRARY DESTINATION "${_reforge_shaper_install_libdir}"
        RUNTIME DESTINATION "${_reforge_shaper_install_bindir}"
        INCLUDES DESTINATION "${_reforge_shaper_install_includedir}"
    )
    if(NOT SKBUILD AND TARGET reforge_shaper_solver AND NOT BUILD_SHARED_LIBS)
        install(
            FILES "${_reforge_clarabel_static_library}"
            DESTINATION "${_reforge_shaper_install_libdir}"
        )
    endif()
    set(_reforge_shaper_public_headers
        include/reforge_core/control/model/map_loader.hpp
        include/reforge_core/control/model/model_types.hpp
        include/reforge_core/control/python/windowed_buffer.hpp
        include/reforge_core/control/runtime/base_shaper.hpp
        include/reforge_core/control/runtime/modal_inference.hpp
        include/reforge_core/control/runtime/task_space.hpp
        include/reforge_core/control/runtime/weighting.hpp
        include/reforge_core/control/shaper/config.hpp
        include/reforge_core/control/shaper/modal_inference_strategy.hpp
        include/reforge_core/control/shaper/residual_switch_config.hpp
        include/reforge_core/control/shaper/shaper_window_helpers.hpp
        include/reforge_core/control/window/shaper_window_handle.hpp
        include/reforge_core/native/common/array_types.hpp
        include/reforge_core/native/common/errors.hpp
        include/reforge_core/util/interpolation.hpp
        include/reforge_core/util/robot_dynamics.hpp
        include/reforge_core/util/timing/joint_limits.hpp
        include/reforge_core/util/timing/joint_trajectory.hpp
        include/reforge_core/util/timing/resampling.hpp
    )
    if(TARGET reforge_shaper_solver)
        list(APPEND _reforge_shaper_public_headers
            include/reforge_core/control/shaper/modal_switch_optimizer.hpp
            include/reforge_core/control/shaper/residual_alignment.hpp
            include/reforge_core/control/shaper/residual_switch.hpp
            include/reforge_core/control/shaper/windowing.hpp
            include/reforge_core/util/trajopt/traj_qp.hpp
        )
    endif()
    if(TARGET reforge_shaper_backend)
        list(APPEND _reforge_shaper_public_headers
            include/reforge_core/control/shaper/backend/backend_configuration.hpp
            include/reforge_core/control/shaper/backend/backend_requests.hpp
            include/reforge_core/control/shaper/backend/native_shaper.hpp
        )
    endif()
    foreach(_reforge_shaper_header IN LISTS _reforge_shaper_public_headers)
        get_filename_component(
            _reforge_shaper_header_directory
            "${_reforge_shaper_header}"
            DIRECTORY
        )
        file(
            RELATIVE_PATH
            _reforge_shaper_header_install_directory
            "${CMAKE_CURRENT_SOURCE_DIR}/include"
            "${CMAKE_CURRENT_SOURCE_DIR}/${_reforge_shaper_header_directory}"
        )
        install(
            FILES "${_reforge_shaper_header}"
            DESTINATION
                "${_reforge_shaper_install_includedir}/${_reforge_shaper_header_install_directory}"
        )
    endforeach()
    if(NOT SKBUILD AND REFORGE_SHAPER_INSTALL_RUNTIME_DEPENDENCIES)
        set(_reforge_shaper_runtime_dependency_destination
            "${CMAKE_INSTALL_LIBDIR}"
        )
        if(REFORGE_SHAPER_RUNTIME_DEPENDENCY_INSTALL_SUBDIR)
            if(IS_ABSOLUTE
                "${REFORGE_SHAPER_RUNTIME_DEPENDENCY_INSTALL_SUBDIR}"
            )
                message(FATAL_ERROR
                    "REFORGE_SHAPER_RUNTIME_DEPENDENCY_INSTALL_SUBDIR must "
                    "be relative."
                )
            endif()
            set(_reforge_shaper_runtime_dependency_destination
                "${CMAKE_INSTALL_LIBDIR}/${REFORGE_SHAPER_RUNTIME_DEPENDENCY_INSTALL_SUBDIR}"
            )
        endif()
        set(_reforge_shaper_dependency_include_regexes)
        foreach(_reforge_shaper_dependency_prefix IN LISTS CMAKE_PREFIX_PATH)
            if(IS_DIRECTORY "${_reforge_shaper_dependency_prefix}/lib")
                list(APPEND _reforge_shaper_dependency_include_regexes
                    "^${_reforge_shaper_dependency_prefix}/lib/.*"
                )
            endif()
        endforeach()
        if(NOT _reforge_shaper_dependency_include_regexes)
            message(FATAL_ERROR
                "REFORGE_SHAPER_INSTALL_RUNTIME_DEPENDENCIES requires at "
                "least one CMAKE_PREFIX_PATH entry with a lib directory."
            )
        endif()
        install(
            RUNTIME_DEPENDENCY_SET ReforgeShaperRuntimeDependencies
            DESTINATION "${_reforge_shaper_runtime_dependency_destination}"
            POST_INCLUDE_REGEXES
                ${_reforge_shaper_dependency_include_regexes}
            POST_EXCLUDE_REGEXES
                "^/lib/.*"
                "^/lib64/.*"
                "^/usr/lib/.*"
                "^/usr/lib64/.*"
        )
    endif()
    install(
        FILES
            "${_reforge_shaper_generated_include_dir}/reforge_core/native/common/export.hpp"
        DESTINATION
            "${_reforge_shaper_install_includedir}/reforge_core/native/common"
    )
    if(NOT SKBUILD)
        install(
            DIRECTORY examples/reforge_shaper_demo/
            DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/reforge-core-shaper/examples"
            FILES_MATCHING
                PATTERN "CMakeLists.txt"
                PATTERN "README.md"
                PATTERN "*.cpp"
        )
        if(TARGET reforge_shaper_backend)
            install(
                DIRECTORY examples/reforge_shaper_backend_demo/
                DESTINATION
                    "${CMAKE_INSTALL_DATADIR}/doc/reforge-core-shaper/examples/backend"
                FILES_MATCHING
                    PATTERN "CMakeLists.txt"
                    PATTERN "README.md"
                    PATTERN "*.cpp"
            )
        endif()
    endif()

    set(REFORGE_SHAPER_CONFIG_DEPENDENCY_DECLARATIONS
        "find_dependency(Eigen3 REQUIRED NO_MODULE)\n"
    )
    if(NOT BUILD_SHARED_LIBS)
        string(APPEND REFORGE_SHAPER_CONFIG_DEPENDENCY_DECLARATIONS
            "find_dependency(pinocchio 4 CONFIG REQUIRED)\n"
        )
        if(TARGET reforge_shaper_solver)
            string(APPEND REFORGE_SHAPER_CONFIG_DEPENDENCY_DECLARATIONS
                "\n"
                "if(\n"
                "    EXISTS \"\${PACKAGE_PREFIX_DIR}/${_reforge_shaper_install_libdir}/libclarabel_c.a\"\n"
                "    AND NOT TARGET reforge_clarabel_c_static\n"
                ")\n"
                "    add_library(reforge_clarabel_c_static STATIC IMPORTED)\n"
                "    set_target_properties(reforge_clarabel_c_static PROPERTIES\n"
                "        IMPORTED_LOCATION\n"
                "            \"\${PACKAGE_PREFIX_DIR}/${_reforge_shaper_install_libdir}/libclarabel_c.a\"\n"
                "    )\n"
                "endif()\n"
            )
        endif()
    endif()

    configure_package_config_file(
        cmake/ReforgeShaperConfig.cmake.in
        "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperConfig.cmake"
        INSTALL_DESTINATION
            "${_reforge_shaper_install_libdir}/cmake/ReforgeShaper"
    )
    write_basic_package_version_file(
        "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperConfigVersion.cmake"
        VERSION "${REFORGE_CORE_VERSION}"
        COMPATIBILITY SameMajorVersion
    )
    install(
        EXPORT ReforgeShaperTargets
        FILE ReforgeShaperTargets.cmake
        NAMESPACE ReforgeShaper::
        DESTINATION "${_reforge_shaper_install_libdir}/cmake/ReforgeShaper"
    )
    install(
        FILES
            "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperConfig.cmake"
            "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperConfigVersion.cmake"
        DESTINATION "${_reforge_shaper_install_libdir}/cmake/ReforgeShaper"
    )
    if(NOT SKBUILD AND TARGET reforge_shaper_ros2)
        if(BUILD_SHARED_LIBS)
            set_target_properties(
                reforge_shaper_ros2
                PROPERTIES INSTALL_RPATH "${REFORGE_SHAPER_INSTALL_RPATH}"
            )
        endif()
        install(
            TARGETS reforge_shaper_ros2
            EXPORT ReforgeShaperRos2Targets
            ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
            LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
            RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
            INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
        )
        install(
            FILES
                include/reforge_core/control/shaper/ros2/joint_trajectory_adapter.hpp
            DESTINATION
                "${CMAKE_INSTALL_INCLUDEDIR}/reforge_core/control/shaper/ros2"
        )
        configure_package_config_file(
            cmake/ReforgeShaperRos2Config.cmake.in
            "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperRos2Config.cmake"
            INSTALL_DESTINATION
                "${CMAKE_INSTALL_LIBDIR}/cmake/ReforgeShaperRos2"
        )
        write_basic_package_version_file(
            "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperRos2ConfigVersion.cmake"
            VERSION "${REFORGE_CORE_VERSION}"
            COMPATIBILITY SameMajorVersion
        )
        install(
            EXPORT ReforgeShaperRos2Targets
            FILE ReforgeShaperRos2Targets.cmake
            NAMESPACE ReforgeShaper::
            DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ReforgeShaperRos2"
        )
        install(
            FILES
                "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperRos2Config.cmake"
                "${CMAKE_CURRENT_BINARY_DIR}/ReforgeShaperRos2ConfigVersion.cmake"
            DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ReforgeShaperRos2"
        )
    endif()
endif()  # TARGET reforge_shaper_common

endif()  # REFORGE_BUILD_SHAPER

if(REFORGE_BUILD_JOINT_TRACKER)
    reforge_native_materialize_clarabel_for_skbuild()

    if(NOT REFORGE_SHAPER_CLARABEL_ROOT)
        message(FATAL_ERROR
            "REFORGE_BUILD_JOINT_TRACKER requires "
            "REFORGE_SHAPER_CLARABEL_ROOT for normal native builds."
        )
    endif()
    if(NOT TARGET reforge_clarabel_c_static)
        if(NOT IS_DIRECTORY "${REFORGE_SHAPER_CLARABEL_ROOT}/include")
            message(FATAL_ERROR
                "REFORGE_SHAPER_CLARABEL_ROOT must name the locked "
                "Clarabel.cpp source root."
            )
        endif()
        set(
            _reforge_joint_tracker_clarabel_static_library
            "${REFORGE_SHAPER_CLARABEL_ROOT}/rust_wrapper/target/release/libclarabel_c.a"
        )
        if(NOT EXISTS "${_reforge_joint_tracker_clarabel_static_library}")
            message(FATAL_ERROR
                "The locked Clarabel static library is missing: "
                "${_reforge_joint_tracker_clarabel_static_library}"
            )
        endif()
        add_library(reforge_clarabel_c_static STATIC IMPORTED GLOBAL)
        set_target_properties(reforge_clarabel_c_static PROPERTIES
            IMPORTED_LOCATION "${_reforge_joint_tracker_clarabel_static_library}"
            INTERFACE_INCLUDE_DIRECTORIES
                "${REFORGE_SHAPER_CLARABEL_ROOT}/include"
            INTERFACE_LINK_OPTIONS
                "$<$<PLATFORM_ID:Linux>:LINKER:--exclude-libs,libclarabel_c.a>"
        )
    endif()

    find_package(Eigen3 REQUIRED NO_MODULE)
    if(REFORGE_JOINT_TRACKER_BUILD_PYTHON_BINDINGS)
        set(PYBIND11_FINDPYTHON ON)
        find_package(pybind11 CONFIG REQUIRED)
    endif()
    if(NOT TARGET nlohmann_json::nlohmann_json)
        find_package(nlohmann_json 3.12.0 EXACT CONFIG QUIET)
    endif()
    if(TARGET nlohmann_json::nlohmann_json)
        get_target_property(
            _reforge_joint_tracker_nlohmann_include_dir
            nlohmann_json::nlohmann_json
            INTERFACE_INCLUDE_DIRECTORIES
        )
    elseif(
        REFORGE_NLOHMANN_JSON_INCLUDE_DIR
        AND EXISTS
            "${REFORGE_NLOHMANN_JSON_INCLUDE_DIR}/nlohmann/json.hpp"
    )
        set(_reforge_joint_tracker_nlohmann_include_dir
            "${REFORGE_NLOHMANN_JSON_INCLUDE_DIR}"
        )
    else()
        message(FATAL_ERROR
            "Joint Tracker native model loading requires nlohmann_json "
            "3.12.0. Install a discoverable CMake package or pass "
            "-DREFORGE_NLOHMANN_JSON_INCLUDE_DIR=<include-dir>."
        )
    endif()

    file(GLOB _reforge_joint_tracker_public_headers CONFIGURE_DEPENDS
        "${CMAKE_CURRENT_SOURCE_DIR}/include/reforge_core/joint_tracker/*.hpp"
    )
    set(
        REFORGE_JOINT_TRACKER_MODEL_SUMMARY_FIXTURE
        "${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/joint_tracker/example_model_summary.json"
        CACHE FILEPATH
        "Python-generated Joint Tracker model summary fixture for native tests"
    )
    set(
        REFORGE_JOINT_TRACKER_STATE_SPACE_FIXTURE
        "${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/joint_tracker/state_space_prediction_fixture.json"
        CACHE FILEPATH
        "Python-generated Joint Tracker state-space fixture for native tests"
    )
    set(
        REFORGE_JOINT_TRACKER_FULL_TRAJECTORY_FIXTURE
        "${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/joint_tracker/full_trajectory_qp_fixture.json"
        CACHE FILEPATH
        "Python-generated Joint Tracker full-trajectory QP fixture for native tests"
    )
    set(
        REFORGE_JOINT_TRACKER_STREAMING_WINDOW_FIXTURE
        "${CMAKE_CURRENT_SOURCE_DIR}/tests/fixtures/joint_tracker/streaming_window_fixture.json"
        CACHE FILEPATH
        "Python-generated Joint Tracker streaming-window fixture for native tests"
    )

    if(SKBUILD)
        add_library(reforge_joint_tracker STATIC
            src/joint_tracker/joint_tracker.cpp
            src/joint_tracker/model_loader.cpp
            src/joint_tracker/sample_adapter.cpp
            src/joint_tracker/state_space.cpp
            src/joint_tracker/trajectory_optimizer.cpp
            src/solver/clarabel_solver.cpp
        )
    else()
        if(NOT BUILD_SHARED_LIBS)
            message(FATAL_ERROR
                "Normal Joint Tracker SDK builds require "
                "-DBUILD_SHARED_LIBS=ON so Clarabel remains private."
            )
        endif()
        add_library(reforge_joint_tracker SHARED
            src/joint_tracker/joint_tracker.cpp
            src/joint_tracker/model_loader.cpp
            src/joint_tracker/sample_adapter.cpp
            src/joint_tracker/state_space.cpp
            src/joint_tracker/trajectory_optimizer.cpp
            src/solver/clarabel_solver.cpp
        )
    endif()
    add_library(ReforgeJointTracker::joint_tracker ALIAS reforge_joint_tracker)
    target_compile_features(reforge_joint_tracker PUBLIC cxx_std_17)
    set_target_properties(reforge_joint_tracker PROPERTIES
        CXX_EXTENSIONS OFF
        EXPORT_NAME joint_tracker
        POSITION_INDEPENDENT_CODE ON
    )
    target_compile_definitions(reforge_joint_tracker
        PRIVATE REFORGE_SHAPER_EXPORT=
    )
    target_include_directories(reforge_joint_tracker
        PUBLIC
            "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
            "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
        PRIVATE
            "${CMAKE_CURRENT_SOURCE_DIR}/src"
            "${REFORGE_SHAPER_CLARABEL_ROOT}/include"
            "${_reforge_joint_tracker_nlohmann_include_dir}"
    )
    # Eigen and Clarabel are private implementation dependencies. Keep both out
    # of the installed target's link interface so consumers need only the shared
    # Joint Tracker library.
    target_link_libraries(
        reforge_joint_tracker
        PRIVATE
            $<BUILD_INTERFACE:Eigen3::Eigen>
            reforge_clarabel_c_static
    )

    if(BUILD_TESTING)
        set(_reforge_joint_tracker_header_hygiene_dir
            "${CMAKE_CURRENT_BINARY_DIR}/joint_tracker_header_hygiene"
        )
        file(MAKE_DIRECTORY "${_reforge_joint_tracker_header_hygiene_dir}")
        foreach(_reforge_joint_tracker_header
                IN LISTS _reforge_joint_tracker_public_headers)
            file(
                RELATIVE_PATH
                _reforge_joint_tracker_header_include
                "${CMAKE_CURRENT_SOURCE_DIR}/include"
                "${_reforge_joint_tracker_header}"
            )
            string(
                REPLACE "/" "_"
                _reforge_joint_tracker_header_target_suffix
                "${_reforge_joint_tracker_header_include}"
            )
            string(
                REPLACE "." "_"
                _reforge_joint_tracker_header_target_suffix
                "${_reforge_joint_tracker_header_target_suffix}"
            )
            set(_reforge_joint_tracker_header_hygiene_source
                "${_reforge_joint_tracker_header_hygiene_dir}/${_reforge_joint_tracker_header_target_suffix}.cpp"
            )
            file(WRITE
                "${_reforge_joint_tracker_header_hygiene_source}"
                "#include \"${_reforge_joint_tracker_header_include}\"\n"
                "\n"
                "int main() {\n"
                "    return 0;\n"
                "}\n"
            )
            add_executable(
                "reforge_joint_tracker_header_hygiene_${_reforge_joint_tracker_header_target_suffix}"
                "${_reforge_joint_tracker_header_hygiene_source}"
            )
            target_compile_features(
                "reforge_joint_tracker_header_hygiene_${_reforge_joint_tracker_header_target_suffix}"
                PRIVATE cxx_std_17
            )
            target_include_directories(
                "reforge_joint_tracker_header_hygiene_${_reforge_joint_tracker_header_target_suffix}"
                PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/include"
            )
            set_target_properties(
                "reforge_joint_tracker_header_hygiene_${_reforge_joint_tracker_header_target_suffix}"
                PROPERTIES CXX_EXTENSIONS OFF
            )
            add_test(
                NAME
                    "reforge_joint_tracker_header_hygiene_${_reforge_joint_tracker_header_target_suffix}"
                COMMAND
                    "reforge_joint_tracker_header_hygiene_${_reforge_joint_tracker_header_target_suffix}"
            )
        endforeach()
        set(_reforge_joint_tracker_no_assert_script
            "${CMAKE_CURRENT_BINARY_DIR}/CheckJointTrackerNativeNoAssert.cmake"
        )
        file(WRITE
            "${_reforge_joint_tracker_no_assert_script}"
            "set(_reforge_joint_tracker_assert_dir \"${CMAKE_CURRENT_SOURCE_DIR}/tests/joint_tracker\")\n"
        )
        file(APPEND
            "${_reforge_joint_tracker_no_assert_script}"
            [=[
file(GLOB_RECURSE _reforge_joint_tracker_assert_sources
    "${_reforge_joint_tracker_assert_dir}/*.cc"
    "${_reforge_joint_tracker_assert_dir}/*.cpp"
    "${_reforge_joint_tracker_assert_dir}/*.cxx"
    "${_reforge_joint_tracker_assert_dir}/*.h"
    "${_reforge_joint_tracker_assert_dir}/*.hpp"
)
set(_reforge_joint_tracker_assert_matches "")
foreach(_reforge_joint_tracker_assert_source
        IN LISTS _reforge_joint_tracker_assert_sources)
    file(READ "${_reforge_joint_tracker_assert_source}"
        _reforge_joint_tracker_assert_source_text)
    string(
        REGEX MATCH
        "(^|[^A-Za-z0-9_])assert[ \t\r\n]*[(]"
        _reforge_joint_tracker_assert_match
        "${_reforge_joint_tracker_assert_source_text}"
    )
    if(_reforge_joint_tracker_assert_match)
        list(APPEND _reforge_joint_tracker_assert_matches
            "${_reforge_joint_tracker_assert_source}")
    endif()
endforeach()
if(_reforge_joint_tracker_assert_matches)
    list(JOIN _reforge_joint_tracker_assert_matches "\n  "
        _reforge_joint_tracker_assert_match_text)
    message(FATAL_ERROR
        "Native Joint Tracker tests must not use assert() because Release "
        "builds define NDEBUG. Matches:\n  "
        "${_reforge_joint_tracker_assert_match_text}"
    )
endif()
message(STATUS "No assert() calls found in native Joint Tracker tests.")
]=]
        )
        add_test(
            NAME reforge_joint_tracker_native_no_assert_tests
            COMMAND
                "${CMAKE_COMMAND}"
                -P "${_reforge_joint_tracker_no_assert_script}"
        )
        add_executable(reforge_joint_tracker_model_tests
            tests/joint_tracker/test_model_loader.cpp
        )
        target_compile_features(
            reforge_joint_tracker_model_tests PRIVATE cxx_std_17)
        target_compile_definitions(reforge_joint_tracker_model_tests
            PRIVATE
                REFORGE_JOINT_TRACKER_EXAMPLE_MODELS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../robot/example_usage/joint_tracker/example_models"
                REFORGE_JOINT_TRACKER_MODEL_SUMMARY_FIXTURE="${REFORGE_JOINT_TRACKER_MODEL_SUMMARY_FIXTURE}"
        )
        target_include_directories(reforge_joint_tracker_model_tests
            PRIVATE
                "${CMAKE_CURRENT_SOURCE_DIR}/src"
                "${_reforge_joint_tracker_nlohmann_include_dir}"
        )
        target_link_libraries(reforge_joint_tracker_model_tests
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        add_test(
            NAME reforge_joint_tracker_model_tests
            COMMAND reforge_joint_tracker_model_tests
        )
        add_executable(reforge_joint_tracker_state_space_tests
            tests/joint_tracker/test_state_space.cpp
        )
        target_compile_features(
            reforge_joint_tracker_state_space_tests PRIVATE cxx_std_17)
        target_compile_definitions(reforge_joint_tracker_state_space_tests
            PRIVATE
                REFORGE_JOINT_TRACKER_EXAMPLE_MODELS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../robot/example_usage/joint_tracker/example_models"
                REFORGE_JOINT_TRACKER_STATE_SPACE_FIXTURE="${REFORGE_JOINT_TRACKER_STATE_SPACE_FIXTURE}"
        )
        target_include_directories(reforge_joint_tracker_state_space_tests
            PRIVATE
                "${CMAKE_CURRENT_SOURCE_DIR}/src"
                "${_reforge_joint_tracker_nlohmann_include_dir}"
        )
        target_link_libraries(reforge_joint_tracker_state_space_tests
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        add_test(
            NAME reforge_joint_tracker_state_space_tests
            COMMAND reforge_joint_tracker_state_space_tests
        )
        add_executable(reforge_joint_tracker_full_trajectory_tests
            tests/joint_tracker/test_full_trajectory.cpp
        )
        target_compile_features(
            reforge_joint_tracker_full_trajectory_tests PRIVATE cxx_std_17)
        target_compile_definitions(reforge_joint_tracker_full_trajectory_tests
            PRIVATE
                REFORGE_JOINT_TRACKER_EXAMPLE_MODELS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../robot/example_usage/joint_tracker/example_models"
                REFORGE_JOINT_TRACKER_FULL_TRAJECTORY_FIXTURE="${REFORGE_JOINT_TRACKER_FULL_TRAJECTORY_FIXTURE}"
        )
        target_include_directories(reforge_joint_tracker_full_trajectory_tests
            PRIVATE
                "${CMAKE_CURRENT_SOURCE_DIR}/src"
                "${_reforge_joint_tracker_nlohmann_include_dir}"
        )
        target_link_libraries(reforge_joint_tracker_full_trajectory_tests
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        add_test(
            NAME reforge_joint_tracker_full_trajectory_tests
            COMMAND reforge_joint_tracker_full_trajectory_tests
        )
        add_executable(reforge_joint_tracker_streaming_tests
            tests/joint_tracker/test_streaming.cpp
        )
        target_compile_features(
            reforge_joint_tracker_streaming_tests PRIVATE cxx_std_17)
        target_compile_definitions(reforge_joint_tracker_streaming_tests
            PRIVATE
                REFORGE_JOINT_TRACKER_EXAMPLE_MODELS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../robot/example_usage/joint_tracker/example_models"
                REFORGE_JOINT_TRACKER_STREAMING_WINDOW_FIXTURE="${REFORGE_JOINT_TRACKER_STREAMING_WINDOW_FIXTURE}"
        )
        target_include_directories(reforge_joint_tracker_streaming_tests
            PRIVATE
                "${CMAKE_CURRENT_SOURCE_DIR}/src"
                "${_reforge_joint_tracker_nlohmann_include_dir}"
        )
        target_link_libraries(reforge_joint_tracker_streaming_tests
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        add_test(
            NAME reforge_joint_tracker_streaming_tests
            COMMAND reforge_joint_tracker_streaming_tests
        )
        add_executable(reforge_joint_tracker_sample_adapter_tests
            tests/joint_tracker/test_sample_adapter.cpp
        )
        target_compile_features(
            reforge_joint_tracker_sample_adapter_tests PRIVATE cxx_std_17)
        target_compile_definitions(reforge_joint_tracker_sample_adapter_tests
            PRIVATE
                REFORGE_JOINT_TRACKER_EXAMPLE_MODELS_DIR="${CMAKE_CURRENT_SOURCE_DIR}/../../robot/example_usage/joint_tracker/example_models"
        )
        target_link_libraries(reforge_joint_tracker_sample_adapter_tests
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        add_test(
            NAME reforge_joint_tracker_sample_adapter_tests
            COMMAND reforge_joint_tracker_sample_adapter_tests
        )
        add_executable(reforge_joint_tracker_driver_loop_tests
            tests/joint_tracker/test_driver_loop.cpp
        )
        target_compile_features(
            reforge_joint_tracker_driver_loop_tests PRIVATE cxx_std_17)
        target_link_libraries(reforge_joint_tracker_driver_loop_tests
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        add_test(
            NAME reforge_joint_tracker_driver_loop_tests
            COMMAND reforge_joint_tracker_driver_loop_tests
        )
        foreach(_reforge_joint_tracker_test_target IN ITEMS
                reforge_joint_tracker_model_tests
                reforge_joint_tracker_state_space_tests
                reforge_joint_tracker_full_trajectory_tests
                reforge_joint_tracker_streaming_tests
                reforge_joint_tracker_sample_adapter_tests
                reforge_joint_tracker_driver_loop_tests
        )
            reforge_native_keep_assertions_enabled(
                "${_reforge_joint_tracker_test_target}")
        endforeach()
    endif()

    if(REFORGE_JOINT_TRACKER_BUILD_PYTHON_BINDINGS)
        pybind11_add_module(_native_joint_tracker NO_EXTRAS
            bindings/python/reforge_core/control/native_joint_tracker_module.cpp
        )
        target_compile_features(_native_joint_tracker PRIVATE cxx_std_17)
        target_include_directories(
            _native_joint_tracker
            PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/bindings/python"
        )
        target_link_libraries(
            _native_joint_tracker
            PRIVATE ReforgeJointTracker::joint_tracker
        )
        install(TARGETS _native_joint_tracker
            LIBRARY DESTINATION "${_reforge_core_python_install_dir}"
            RUNTIME DESTINATION "${_reforge_core_python_install_dir}"
        )
    endif()

    if(NOT SKBUILD)
        install(
            TARGETS reforge_joint_tracker
            EXPORT ReforgeJointTrackerTargets
            LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
            RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"
            INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
        )
        install(
            DIRECTORY include/reforge_core/joint_tracker/
            DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/reforge_core/joint_tracker"
            FILES_MATCHING
                PATTERN "*.hpp"
        )
        install(
            DIRECTORY examples/reforge_joint_tracker_driver_loop_demo/
            DESTINATION
                "${CMAKE_INSTALL_DATADIR}/reforge-core-joint-tracker/examples"
            FILES_MATCHING
                PATTERN "CMakeLists.txt"
                PATTERN "*.cpp"
                PATTERN "*.md"
        )
        configure_package_config_file(
            cmake/ReforgeJointTrackerConfig.cmake.in
            "${CMAKE_CURRENT_BINARY_DIR}/ReforgeJointTrackerConfig.cmake"
            INSTALL_DESTINATION
                "${CMAKE_INSTALL_LIBDIR}/cmake/ReforgeJointTracker"
        )
        write_basic_package_version_file(
            "${CMAKE_CURRENT_BINARY_DIR}/ReforgeJointTrackerConfigVersion.cmake"
            VERSION "${REFORGE_CORE_VERSION}"
            COMPATIBILITY SameMajorVersion
        )
        install(
            EXPORT ReforgeJointTrackerTargets
            FILE ReforgeJointTrackerTargets.cmake
            NAMESPACE ReforgeJointTracker::
            DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ReforgeJointTracker"
        )
        install(
            FILES
                "${CMAKE_CURRENT_BINARY_DIR}/ReforgeJointTrackerConfig.cmake"
                "${CMAKE_CURRENT_BINARY_DIR}/ReforgeJointTrackerConfigVersion.cmake"
            DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ReforgeJointTracker"
        )
    endif()
endif()
