Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace docker build system with makefile approach #90

Open
wants to merge 3 commits into
base: humble
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
71 changes: 42 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
This tool aims to ease the micro-ROS integration in a STM32CubeMX/IDE project.

- [micro-ROS for STM32CubeMX/IDE](#micro-ros-for-stm32cubemxide)
- [Requirements](#requirements)
- [Middlewares available](#middlewares-available)
- [Using this package with STM32CubeMX](#using-this-package-with-stm32cubemx)
- [Using this package with STM32CubeIDE](#using-this-package-with-stm32cubeide)
Expand All @@ -17,6 +18,16 @@ This tool aims to ease the micro-ROS integration in a STM32CubeMX/IDE project.
- [Purpose of the Project](#purpose-of-the-project)
- [License](#license)
- [Known Issues/Limitations](#known-issueslimitations)

## Requirements

- Install `rsync`: `apt -y install rsync`
- [Install colcon](https://colcon.readthedocs.io/en/released/user/installation.html) and dependencies, for example with:

```bash
pip3 install colcon-common-extensions catkin_pkg lark-parser empy
```

## Middlewares available

This package support the usage of micro-ROS on top of two different middlewares:
Expand All @@ -31,53 +42,54 @@ This package support the usage of micro-ROS on top of two different middlewares:
4. Configure the transport interface on the STM32CubeMX project, check the [Transport configuration](#Transport-configuration) section for instructions on the custom transports provided.
5. Modify the generated `Makefile` to include the following code **before the `build the application` section**:

<!-- # Removing heap4 manager while being polite with STM32CubeMX
TMPVAR := $(C_SOURCES)
C_SOURCES := $(filter-out Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c, $(TMPVAR)) -->
<!-- # Removing heap4 manager while being polite with STM32CubeMX
TMPVAR := $(C_SOURCES)
C_SOURCES := $(filter-out Middlewares/Third_Party/FreeRTOS/Source/portable/MemMang/heap_4.c, $(TMPVAR)) -->

```makefile
#######################################
# micro-ROS addons
#######################################
LDFLAGS += micro_ros_stm32cubemx_utils/microros_static_library/libmicroros/libmicroros.a
C_INCLUDES += -Imicro_ros_stm32cubemx_utils/microros_static_library/libmicroros/microros_include
<!-- TODO: Check how to fix flags here -->

# Add micro-ROS utils
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c
```makefile
#######################################
# micro-ROS addons
#######################################
LDFLAGS += micro_ros_stm32cubemx_utils/libmicroros/libmicroros.a
C_INCLUDES += -Imicro_ros_stm32cubemx_utils/libmicroros/include

# Set here the custom transport implementation
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/dma_transport.c
# Add micro-ROS utils
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/custom_memory_manager.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_allocators.c
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_time.c

print_cflags:
@echo $(CFLAGS)
```
# Set here the custom transport implementation
C_SOURCES += micro_ros_stm32cubemx_utils/extra_sources/microros_transports/usb_transport.c

6. Execute the static library generation tool. Compiler flags will retrieved automatically from your `Makefile` and user will be prompted to check if they are correct.
print_cflags:
@echo $(CFLAGS)
```

6. Execute the static library generation tool. Compiler flags will retrieved automatically from your `Makefile` and user will be prompted to check if they are correct.

```bash
docker pull microros/micro_ros_static_library_builder:humble
docker run -it --rm -v $(pwd):/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library microros/micro_ros_static_library_builder:humble
```
```bash
./micro_ros_stm32cubemx_utils/library_generation//library_generation.sh
```

1. Modify your `main.c` to use micro-ROS. An example application can be found in `sample_main.c`.
2. Continue your usual workflow building your project and flashing the binary:

```bash
make -j$(nproc)
```
```bash
make -j$(nproc)
```

## Using this package with STM32CubeIDE

micro-ROS can be used with SMT32CubeIDE following these steps:

1. Clone this repository in your STM32CubeIDE project folder
2. Go to `Project -> Settings -> C/C++ Build -> Settings -> Build Steps Tab` and in `Pre-build steps` add:

```bash
docker pull microros/micro_ros_static_library_builder:humble && docker run --rm -v ${workspace_loc:/${ProjName}}:/project --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:humble
```
```bash
./micro_ros_stm32cubemx_utils/library_generation//library_generation.sh
```

3. Add micro-ROS include directory. In `Project -> Settings -> C/C++ Build -> Settings -> Tool Settings Tab -> MCU GCC Compiler -> Include paths` add `micro_ros_stm32cubemx_utils/microros_static_library_ide/libmicroros/include`
4. Add the micro-ROS precompiled library. In `Project -> Settings -> C/C++ Build -> Settings -> MCU GCC Linker -> Libraries`
Expand All @@ -91,6 +103,7 @@ docker pull microros/micro_ros_static_library_builder:humble && docker run --rm
6. Make sure that if you are using FreeRTOS, the micro-ROS task **has more than 10 kB of stack**: [Detail](.images/Set_freertos_stack.jpg)
7. Configure the transport interface on the STM32CubeMX project, check the [Transport configuration](#Transport-configuration) section for instructions on the custom transports provided.
8. Build and run your project

## Transport configuration

Available transport for this platform are:
Expand Down
2 changes: 1 addition & 1 deletion embeddedrtps.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ This instructions are an approach to a [STMCubeIDE v1.7.0](https://www.st.com/en
10. Go to `Project -> Settings -> C/C++ Build -> Settings -> Build Steps Tab` and in `Pre-build steps` add:

```bash
docker pull microros/micro_ros_static_library_builder:humble && docker run --rm -v ${workspace_loc:/${ProjName}}:/project --env MICROROS_USE_EMBEDDEDRTPS=ON --env MICROROS_LIBRARY_FOLDER=micro_ros_stm32cubemx_utils/microros_static_library_ide microros/micro_ros_static_library_builder:humble
export MICROROS_USE_EMBEDDEDRTPS=ON && cd ../micro_ros_stm32cubemx_utils/microros_static_library_ide/library_generation && ./library_generation.sh
```

12. Add the following source code files to your project, dragging them to source folder:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

includes = [x for x in text if x.startswith("-I")]
includes = list(set(includes))
includes = [x.replace("../", "/project/") for x in includes]
includes = [x.replace("../", "../../../") for x in includes]

out = "-ffunction-sections -fdata-sections -DSTM32CUBEIDE"

Expand Down
160 changes: 160 additions & 0 deletions library_generation/libmicroros.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
COMPONENT_DIR = $(shell pwd)
INSTALL_DIR = $(COMPONENT_DIR)/../libmicroros

DEBUG ?= 0

ifeq ($(DEBUG), 1)
BUILD_TYPE = Debug
else
BUILD_TYPE = Release
endif

ifeq ($(MICROROS_USE_EMBEDDEDRTPS), "ON")
META_FILE = $(COMPONENT_DIR)/colcon-embeddedrtps.meta
else
META_FILE = $(COMPONENT_DIR)/colcon.meta
endif

X_CC := arm-none-eabi-gcc
X_CXX := arm-none-eabi-g++
X_AR := arm-none-eabi-ar
X_STRIP := arm-none-eabi-strip
CFLAGS_INTERNAL := $(RET_CFLAGS) -w -DCLOCK_MONOTONIC=0 -D'__attribute__(x)='
CXXFLAGS_INTERNAL := $(RET_CFLAGS) -w -DCLOCK_MONOTONIC=0 -D'__attribute__(x)='

all: $(INSTALL_DIR)/libmicroros.a

clean:
rm -rf $(INSTALL_DIR)

$(INSTALL_DIR)/toolchain.cmake: $(COMPONENT_DIR)/toolchain.cmake.in
rm -f $(INSTALL_DIR)/toolchain.cmake; \
mkdir -p $(INSTALL_DIR); \
cat $(COMPONENT_DIR)/toolchain.cmake.in | \
sed "s/@CMAKE_C_COMPILER@/$(subst /,\/,$(X_CC))/g" | \
sed "s/@CMAKE_CXX_COMPILER@/$(subst /,\/,$(X_CXX))/g" | \
sed "s/@CFLAGS@/$(subst /,\/,$(CFLAGS_INTERNAL))/g" | \
sed "s/@CXXFLAGS@/$(subst /,\/,$(CXXFLAGS_INTERNAL))/g" \
> $(INSTALL_DIR)/toolchain.cmake

$(INSTALL_DIR)/micro_ros_dev/install:
rm -rf $(INSTALL_DIR)/micro_ros_dev; \
mkdir $(INSTALL_DIR)/micro_ros_dev; cd $(INSTALL_DIR)/micro_ros_dev; \
git clone -b humble https://github.com/ament/ament_cmake src/ament_cmake; \
git clone -b humble https://github.com/ament/ament_lint src/ament_lint; \
git clone -b humble https://github.com/ament/ament_package src/ament_package; \
git clone -b humble https://github.com/ament/googletest src/googletest; \
git clone -b humble https://github.com/ros2/ament_cmake_ros src/ament_cmake_ros; \
git clone -b humble https://github.com/ament/ament_index src/ament_index; \
colcon build --cmake-args -DBUILD_TESTING=OFF;

# TODO(acuadros95): Add EmbeddedRTPS conditional
$(INSTALL_DIR)/micro_ros_src/src:
rm -rf $(INSTALL_DIR)/micro_ros_src; \
mkdir $(INSTALL_DIR)/micro_ros_src; cd $(INSTALL_DIR)/micro_ros_src; \
if [ "$(MICROROS_USE_EMBEDDEDRTPS)" = "ON" ]; then \
git clone -b humble https://github.com/micro-ROS/embeddedRTPS src/embeddedRTPS; \
git clone -b humble https://github.com/micro-ROS/rmw_embeddedrtps src/rmw_embeddedrtps; \
else \
git clone -b ros2 https://github.com/eProsima/Micro-XRCE-DDS-Client src/Micro-XRCE-DDS-Client; \
git clone -b humble https://github.com/micro-ROS/rmw_microxrcedds src/rmw_microxrcedds; \
fi; \
git clone -b ros2 https://github.com/eProsima/micro-CDR src/micro-CDR; \
git clone -b humble https://github.com/micro-ROS/rcl src/rcl; \
git clone -b humble https://github.com/ros2/rclc src/rclc; \
git clone -b humble https://github.com/micro-ROS/rcutils src/rcutils; \
git clone -b humble https://github.com/micro-ROS/micro_ros_msgs src/micro_ros_msgs; \
git clone -b humble https://github.com/micro-ROS/rosidl_typesupport src/rosidl_typesupport; \
git clone -b humble https://github.com/micro-ROS/rosidl_typesupport_microxrcedds src/rosidl_typesupport_microxrcedds; \
git clone -b humble https://github.com/ros2/rosidl src/rosidl; \
git clone -b humble https://github.com/ros2/rmw src/rmw; \
git clone -b humble https://github.com/ros2/rcl_interfaces src/rcl_interfaces; \
git clone -b humble https://github.com/ros2/rosidl_defaults src/rosidl_defaults; \
git clone -b humble https://github.com/ros2/unique_identifier_msgs src/unique_identifier_msgs; \
git clone -b humble https://github.com/ros2/common_interfaces src/common_interfaces; \
git clone -b humble https://github.com/ros2/test_interface_files src/test_interface_files; \
git clone -b humble https://github.com/ros2/rmw_implementation src/rmw_implementation; \
git clone -b humble https://github.com/ros2/rcl_logging src/rcl_logging; \
git clone -b humble https://gitlab.com/micro-ROS/ros_tracing/ros2_tracing src/ros2_tracing; \
git clone -b humble https://github.com/micro-ROS/micro_ros_utilities src/micro_ros_utilities; \
git clone -b humble https://github.com/ros2/example_interfaces src/example_interfaces; \
touch src/rosidl/rosidl_typesupport_introspection_cpp/COLCON_IGNORE; \
touch src/rcl_logging/rcl_logging_log4cxx/COLCON_IGNORE; \
touch src/rcl_logging/rcl_logging_spdlog/COLCON_IGNORE; \
touch src/rclc/rclc_examples/COLCON_IGNORE; \
touch src/rcl/rcl_yaml_param_parser/COLCON_IGNORE; \
cp -rf $(COMPONENT_DIR)/extra_packages src/extra_packages || :;

$(INSTALL_DIR)/micro_ros_src/install: $(INSTALL_DIR)/toolchain.cmake $(INSTALL_DIR)/micro_ros_dev/install $(INSTALL_DIR)/micro_ros_src/src
cd $(INSTALL_DIR)/micro_ros_src; \
unset AMENT_PREFIX_PATH; \
unset RMW_IMPLEMENTATION; \
PATH=$(subst /opt/ros/$(ROS_DISTRO)/bin,,$(PATH)); \
. ../micro_ros_dev/install/local_setup.sh; \
colcon build \
--merge-install \
--packages-ignore-regex=.*_cpp \
--metas $(META_FILE) $(COMPONENT_DIR)/../../app_colcon.meta $(USER_COLCON_META) \
--cmake-force-configure \
--cmake-clean-cache \
--cmake-args \
"--no-warn-unused-cli" \
--log-level=ERROR \
-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=OFF \
-DTHIRDPARTY=ON \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTING=OFF \
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
-DCMAKE_TOOLCHAIN_FILE=$(INSTALL_DIR)/toolchain.cmake \
-DCMAKE_VERBOSE_MAKEFILE=OFF;

$(INSTALL_DIR)/libmicroros.a: $(INSTALL_DIR)/micro_ros_src/install
mkdir -p $(INSTALL_DIR)/micro_ros_src/aux; cd $(INSTALL_DIR)/micro_ros_src/aux; \
for file in $$(find $(INSTALL_DIR)/micro_ros_src/install/lib/ -name '*.a'); do \
folder=$$(echo $$file | sed -E "s/(.+)\/(.+).a/\2/"); \
mkdir -p $$folder; cd $$folder; $(AR) x $$file; \
for f in *; do \
mv $$f ../$$folder-$$f; \
done; \
cd ..; rm -rf $$folder; \
done ; \
$(AR) rc -s libmicroros.a *.obj; cp libmicroros.a $(INSTALL_DIR); \
cd ..; rm -rf aux; \
cp -R $(INSTALL_DIR)/micro_ros_src/install/include $(INSTALL_DIR)/include;

rebuild_metas:
export META_PACKAGES=$$(python3 $(COMPONENT_DIR)/get_metas_packages.py $(USER_COLCON_META)); \
cd $(INSTALL_DIR)/micro_ros_src; \
unset AMENT_PREFIX_PATH; \
PATH=$(subst /opt/ros/$(ROS_DISTRO)/bin,,$(PATH)); \
. ../micro_ros_dev/install/local_setup.sh; \
colcon build \
--merge-install \
--packages-ignore-regex=.*_cpp \
--packages-select $$META_PACKAGES \
--metas $(COMPONENT_DIR)/colcon.meta $(COMPONENT_DIR)/../../app_colcon.meta $(USER_COLCON_META) \
--cmake-force-configure \
--cmake-clean-cache \
--cmake-args \
"--no-warn-unused-cli" \
--log-level=ERROR \
-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=OFF \
-DTHIRDPARTY=ON \
-DBUILD_SHARED_LIBS=OFF \
-DBUILD_TESTING=OFF \
-DCMAKE_BUILD_TYPE=$(BUILD_TYPE) \
-DCMAKE_TOOLCHAIN_FILE=$(INSTALL_DIR)/toolchain.cmake \
-DCMAKE_VERBOSE_MAKEFILE=OFF;\
mkdir -p $(INSTALL_DIR)/micro_ros_src/aux; cd $(INSTALL_DIR)/micro_ros_src/aux; \
for file in $$(find $(INSTALL_DIR)/micro_ros_src/install/lib/ -name '*.a'); do \
folder=$$(echo $$file | sed -E "s/(.+)\/(.+).a/\2/"); \
mkdir -p $$folder; cd $$folder; $(AR) x $$file; \
for f in *; do \
mv $$f ../$$folder-$$f; \
done; \
cd ..; rm -rf $$folder; \
done ; \
$(AR) rc -s libmicroros.a *.obj; cp libmicroros.a $(INSTALL_DIR); \
cd ..; rm -rf aux; \
rm -rf $(INSTALL_DIR)/include; \
cp -R $(INSTALL_DIR)/micro_ros_src/install/include $(INSTALL_DIR)/include;
81 changes: 81 additions & 0 deletions library_generation/library_generation.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#!/bin/bash
set -e

export BASE_PATH=$(pwd)/..
export PROJECT_PATH=../../

######## Check existing library ########
if [[ -f "$BASE_PATH/libmicroros/libmicroros.a" && ! -f "$USER_COLCON_META" ]]; then
echo "micro-ROS library found. Skipping..."
echo "Delete libmicroros/ for rebuild."
exit 0
fi

if [ ! -f "$USER_COLCON_META" ]; then
rm -rf $BASE_PATH/libmicroros
fi

if [ "$USER_COLCON_META" ]; then
rm -rf $BASE_PATH/libmicroros
fi

######## Trying to retrieve CFLAGS ########

if [ $(MICROROS_USE_CUBEIDE) ]; then
export RET_CFLAGS=$(find $PROJECT_PATH -type f -name subdir.mk -exec cat {} \; | python3 $BASE_PATH/library_generation/extract_flags.py)
else
# Use CubeMX approach
export RET_CFLAGS=$(cd $PROJECT_PATH && make print_cflags)
fi

if [ $RET_CFLAGS != "" ]; then
echo "Found CFLAGS:"
echo "-------------"
echo $RET_CFLAGS
echo "-------------"
else
echo "Error retrieving croscompiler flags"
exit 1;
fi

echo "Using:"
echo "-------------"
echo $(which arm-none-eabi-gcc)
echo Version: $(arm-none-eabi-gcc -dumpversion)
echo "-------------"

######## Build ########

if [ ! -f "$BASE_PATH/libmicroros/libmicroros.a" ]; then
# If library does not exist build it

######## Add extra packages ########
pushd extra_packages
# Workaround: Copy just tf2_msgs
git clone -b ros2 https://github.com/ros2/geometry2
cp -R geometry2/tf2_msgs tf2_msgs
rm -rf geometry2

if [ -f $extra_packages.repos ]; then
vcs import --input extra_packages.repos
fi
popd > /dev/null


make -f libmicroros.mk
else
# If exists just rebuild
make -f libmicroros.mk rebuild_metas
fi

######## Fix include paths ########
pushd $BASE_PATH/libmicroros/micro_ros_src > /dev/null
INCLUDE_ROS2_PACKAGES=$(colcon list | awk '{print $1}' | awk -v d=" " '{s=(NR==1?s:s d)$0}END{print s}')
popd > /dev/null

for var in ${INCLUDE_ROS2_PACKAGES}; do
if [ -d "$BASE_PATH/libmicroros/include/${var}/${var}" ]; then
rsync -r $BASE_PATH/libmicroros/include/${var}/${var}/* $BASE_PATH/libmicroros/include/${var}
rm -rf $BASE_PATH/libmicroros/include/${var}/${var}
fi
done
21 changes: 21 additions & 0 deletions library_generation/toolchain.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
include(CMakeForceCompiler)

set(CMAKE_SYSTEM_NAME Generic)

set(CMAKE_CROSSCOMPILING 1)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

SET (CMAKE_C_COMPILER_WORKS 1)
SET (CMAKE_CXX_COMPILER_WORKS 1)

set(CMAKE_C_COMPILER @CMAKE_C_COMPILER@)
set(CMAKE_CXX_COMPILER @CMAKE_CXX_COMPILER@)

set(CMAKE_C_FLAGS_INIT "-std=c11 @CFLAGS@" CACHE STRING "" FORCE)
set(CMAKE_CXX_FLAGS_INIT "-std=c++14 @CXXFLAGS@" CACHE STRING "" FORCE)

set(__BIG_ENDIAN__ 0)
Loading