Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
217 changes: 71 additions & 146 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,161 +1,86 @@
cmake_minimum_required(VERSION 3.8)
project(sas_core)

option(ROS2_BUILD "Enable ROS2/ament build (examples + ament integration)" ON)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

#################################
# pybind11 import block [BEGIN] #
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvv #
set(PYBIND11_FINDPYTHON ON) # Fix CMP0148 Warning. https://github.com/pybind/pybind11/issues/4785
add_subdirectory(pybind11)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ #
# pybind11 import block [END] #
###############################

# find dependencies
find_package(ament_cmake REQUIRED)
# Find non-ROS dependencies
find_package(Eigen3 REQUIRED)

##### CPP LIBRARY #####

add_library(${PROJECT_NAME} SHARED
src/sas_clock.cpp
src/sas_core.cpp
src/sas_object.cpp
src/sas_shutdown_signaler.cpp
# sas_robot_driver
src/sas_robot_driver.cpp
src/examples/sas_robot_driver_example.cpp
src/eigen3_std_conversions.cpp
)

ament_target_dependencies(${PROJECT_NAME} Eigen3)

target_include_directories(${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)

ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(Eigen3)

target_link_libraries(${PROJECT_NAME}
-ldqrobotics
Eigen3::Eigen
)

install(
DIRECTORY include/
DESTINATION include
)

install(
TARGETS ${PROJECT_NAME}
EXPORT export_${PROJECT_NAME}
LIBRARY DESTINATION lib
#ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include
)

##END## CPP LIBRARY #####

##### CPP BINARY #####

add_executable(sas_core_example
src/examples/sas_core_example.cpp)

target_link_libraries(sas_core_example
-ldqrobotics
${PROJECT_NAME}
)

install(TARGETS
sas_core_example
DESTINATION lib/${PROJECT_NAME})

##END## CPP BINARY #####

##### CPP BINARY #####

add_executable(sas_clock_example
src/examples/sas_clock_example.cpp)

target_link_libraries(sas_clock_example
${PROJECT_NAME}
)

install(TARGETS
sas_clock_example
DESTINATION lib/${PROJECT_NAME})

##END## CPP BINARY #####

##### CPP BINARY #####

add_executable(sas_clock_sched_fifo_example
src/examples/sas_clock_sched_fifo_example.cpp)

target_link_libraries(sas_clock_sched_fifo_example
${PROJECT_NAME}
##############################
# Pure C++ library #
##############################
include(cmake/cpplib.cmake)

##############################
# Python wrapper (pybind11) #
##############################
if(ROS2_BUILD)
find_package(ament_cmake REQUIRED)
ament_python_install_package(${PROJECT_NAME})
# ament_python_install_package sets PYTHON_INSTALL_DIR — pass it to pythonlib.cmake
set(_SAS_PYTHON_INSTALL_DIR "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}")
endif()
include(cmake/pythonlib.cmake)

##############################
# ROS2 / ament integration #
##############################
if(ROS2_BUILD)
# INTERFACE alias so external ROS packages can link against `sas_core`.
add_library(sas_core INTERFACE)
target_link_libraries(sas_core INTERFACE sas_core_pure)
target_include_directories(sas_core INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)

ament_export_targets(export_${PROJECT_NAME} HAS_LIBRARY_TARGET)
ament_export_dependencies(Eigen3)
ament_export_include_directories(include)

install(
DIRECTORY include/
DESTINATION include
)

install(TARGETS
sas_clock_sched_fifo_example
DESTINATION lib/${PROJECT_NAME})

##END## CPP BINARY #####

##### CPP BINARY #####

add_executable(sas_robot_driver_example
src/examples/sas_robot_driver_example_main.cpp)

target_link_libraries(sas_robot_driver_example
${PROJECT_NAME}
install(
TARGETS sas_core sas_core_pure
EXPORT export_${PROJECT_NAME}
ARCHIVE DESTINATION lib
INCLUDES DESTINATION include
)

install(TARGETS
sas_robot_driver_example
DESTINATION lib/${PROJECT_NAME})

##END## CPP BINARY #####

##### PYBIND11 LIBRARY #####

ament_python_install_package(${PROJECT_NAME})


pybind11_add_module(_${PROJECT_NAME} SHARED
src/sas_core_py.cpp
src/sas_robot_driver_py.cpp
################################################################################
# Example executables
################################################################################
add_executable(sas_core_example src/examples/sas_core_example.cpp)
target_link_libraries(sas_core_example -ldqrobotics sas_core_pure)
install(TARGETS sas_core_example DESTINATION lib/${PROJECT_NAME})

add_executable(sas_clock_example src/examples/sas_clock_example.cpp)
target_link_libraries(sas_clock_example sas_core_pure)
install(TARGETS sas_clock_example DESTINATION lib/${PROJECT_NAME})

add_executable(sas_clock_sched_fifo_example src/examples/sas_clock_sched_fifo_example.cpp)
target_link_libraries(sas_clock_sched_fifo_example sas_core_pure)
install(TARGETS sas_clock_sched_fifo_example DESTINATION lib/${PROJECT_NAME})

add_executable(sas_robot_driver_example src/examples/sas_robot_driver_example_main.cpp)
target_link_libraries(sas_robot_driver_example sas_core_pure)
install(TARGETS sas_robot_driver_example DESTINATION lib/${PROJECT_NAME})

################################################################################
# Python executables
################################################################################
install(PROGRAMS
scripts/sas_clock_example_py.py
scripts/sas_robot_driver_subclass_example_py.py
scripts/sas_clock_sched_fifo_example_py.py
DESTINATION lib/${PROJECT_NAME}
)

target_include_directories(_${PROJECT_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)

target_compile_definitions(_${PROJECT_NAME} PRIVATE IS_SAS_PYTHON_BUILD)
# https://github.com/pybind/pybind11/issues/387
target_link_libraries(_${PROJECT_NAME} PRIVATE ${PROJECT_NAME} -ldqrobotics)

install(TARGETS _${PROJECT_NAME}
DESTINATION "${PYTHON_INSTALL_DIR}/${PROJECT_NAME}"
)

##END## PYBIND11 LIBRARY #####

# According to https://github.com/SmartArmStack/sas_datalogger/blob/78ac681f9cb049c5b9715d215f163565f16b5cdc/CMakeLists.txt
##### PYTHON EXECUTABLES #####
install(PROGRAMS
scripts/sas_clock_example_py.py
scripts/sas_robot_driver_subclass_example_py.py
scripts/sas_clock_sched_fifo_example_py.py
DESTINATION lib/${PROJECT_NAME}
)
##END## PYTHON EXECUTABLES #####

ament_package()
ament_package()
endif()
37 changes: 37 additions & 0 deletions cmake/cpplib.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# sas_core_pure: the pure C++ library (no ROS2/ament dependencies)

find_package(Eigen3 REQUIRED)

# Use CURRENT_LIST_DIR so paths resolve relative to this cmake file
set(_sas_core_pure_dir "${CMAKE_CURRENT_LIST_DIR}/../src")

set(_sas_core_pure_sources
${_sas_core_pure_dir}/sas_clock.cpp
${_sas_core_pure_dir}/sas_core.cpp
${_sas_core_pure_dir}/sas_object.cpp
${_sas_core_pure_dir}/sas_shutdown_signaler.cpp
${_sas_core_pure_dir}/sas_robot_driver.cpp
${_sas_core_pure_dir}/examples/sas_robot_driver_example.cpp
${_sas_core_pure_dir}/eigen3_std_conversions.cpp
)

add_library(sas_core_pure STATIC ${_sas_core_pure_sources})

set_target_properties(sas_core_pure PROPERTIES
POSITION_INDEPENDENT_CODE ON
)

target_include_directories(sas_core_pure
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/../include>
$<INSTALL_INTERFACE:include>
)

target_link_libraries(sas_core_pure
PUBLIC
-ldqrobotics
Eigen3::Eigen
)

unset(_sas_core_pure_dir)
unset(_sas_core_pure_sources)
40 changes: 40 additions & 0 deletions cmake/pythonlib.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Python wrapper module via pybind11

find_package(Python3 REQUIRED COMPONENTS Development)

# pybind11 import block [BEGIN]
# vvvvvvvvvvvvvvvvvvvvvvvvvvvvv #
set(PYBIND11_FINDPYTHON ON) # Fix CMP0148 Warning. https://github.com/pybind/pybind11/issues/4785
# Provide binary directory for out-of-tree include (e.g. when included from standalone_consumer)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../pybind11 ${CMAKE_CURRENT_BINARY_DIR}/pybind11)
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^ #
# pybind11 import block [END] #

# Always build the module as _sas_core regardless of the including project's name
set(_SAS_PY_MODULE_NAME "_sas_core")

pybind11_add_module(${_SAS_PY_MODULE_NAME} SHARED
${CMAKE_CURRENT_LIST_DIR}/../src/sas_core_py.cpp
${CMAKE_CURRENT_LIST_DIR}/../src/sas_robot_driver_py.cpp
)

target_include_directories(${_SAS_PY_MODULE_NAME}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/../include>
$<INSTALL_INTERFACE:include>)

target_compile_definitions(${_SAS_PY_MODULE_NAME} PRIVATE IS_SAS_PYTHON_BUILD)
target_link_libraries(${_SAS_PY_MODULE_NAME} PRIVATE sas_core_pure -ldqrobotics)

# Install path: use _SAS_PYTHON_INSTALL_DIR if set by parent (ROS2/ament),
# otherwise default to the standard Python site-packages location.
if(DEFINED _SAS_PYTHON_INSTALL_DIR)
set(_SAS_PY_INSTALL_DEST "${_SAS_PYTHON_INSTALL_DIR}")
else()
set(_SAS_PY_INSTALL_DEST "lib/python3/dist-packages/sas_core")
endif()

install(TARGETS ${_SAS_PY_MODULE_NAME}
DESTINATION "${_SAS_PY_INSTALL_DEST}")

unset(_SAS_PY_MODULE_NAME)
6 changes: 5 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,8 @@ ENV BASH_ENV="/etc/bash_env"
RUN sudo apt-get update && sudo apt-get upgrade -y
RUN python3 -m pip install --upgrade dqrobotics --break-system-packages
RUN sudo sudo apt-get remove -y ros-jazzy-sas-core
RUN mkdir -p /root/sas_core_devel/src/
RUN mkdir -p /root/sas_core_devel/src/
COPY . /root/sas_core_devel/src/sas_core
COPY test_consumer /root/sas_core_devel/src/test_consumer
# standalone_consumer lives outside the colcon workspace
COPY standalone_consumer /root/standalone_consumer
18 changes: 15 additions & 3 deletions docker/compose.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
services:
sas_core:
build: .
volumes:
- ../../sas_core:/root/sas_core_devel/src/sas_core
build:
context: ..
dockerfile: docker/Dockerfile
environment:
PYTHONUNBUFFERED: 1
command: /bin/bash -c "
Expand All @@ -16,4 +16,16 @@ services:
&& ros2 run sas_core sas_robot_driver_subclass_example_py.py
&& ros2 run sas_core sas_clock_sched_fifo_example
&& ros2 run sas_core sas_clock_sched_fifo_example_py.py
&& ros2 run test_consumer test_consumer
&& echo '--- Running Python import test from test_consumer ---'
&& python3 test_consumer/test/test_python_import.py
&& echo '--- Building standalone_consumer (no ROS2) ---'
&& mkdir -p /root/standalone_build
&& cd /root/standalone_build
&& cmake /root/standalone_consumer -DCMAKE_INSTALL_PREFIX=/root/standalone_install
&& make
&& /root/standalone_build/standalone_consumer
&& echo '--- Running Python import test from standalone_consumer ---'
&& cp /root/standalone_build/_sas_core.*.so /root/sas_core_devel/src/sas_core/sas_core/ 2>/dev/null || true
&& PYTHONPATH=/root/sas_core_devel/src/sas_core python3 /root/standalone_consumer/test/test_python_import.py
"
34 changes: 34 additions & 0 deletions standalone_consumer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
cmake_minimum_required(VERSION 3.8)
project(standalone_consumer)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(Eigen3 REQUIRED)

# Path to the sas_core source tree — required to include cmake modules
set(SAS_CORE_SOURCE_DIR "/root/sas_core_devel/src/sas_core" CACHE PATH "Path to sas_core source")

# Include sas_core pure C++ and Python library definitions (no ROS2/ament needed)
include(${SAS_CORE_SOURCE_DIR}/cmake/cpplib.cmake)
include(${SAS_CORE_SOURCE_DIR}/cmake/pythonlib.cmake)

##############################
# Standalone C++ consumer #
##############################
add_executable(standalone_consumer src/standalone_consumer.cpp)
target_link_libraries(standalone_consumer sas_core_pure)

##############################
# Standalone Python test #
##############################
# The Python test runs as a CTest; it requires the built _sas_core module.
find_package(Python3 REQUIRED COMPONENTS Interpreter)
add_test(
NAME test_python_import
COMMAND ${Python3_EXECUTABLE} test/test_python_import.py
)
set_tests_properties(test_python_import PROPERTIES
ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}:${CMAKE_SOURCE_DIR}/.."
)
Loading