Skip to content

Commit

Permalink
Release 7.1.0
Browse files Browse the repository at this point in the history
Version 7.1.0 contains behind-the-scenes structural improvements to the build system and the CI as well as a few
minor improvements and fixes to state_representation.
  • Loading branch information
domire8 authored Jul 25, 2023
2 parents c40c83c + 6d1e72a commit 7da0c99
Show file tree
Hide file tree
Showing 29 changed files with 426 additions and 64 deletions.
62 changes: 62 additions & 0 deletions .github/workflows/build-release.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: Build and Push Multi-Arch Images

on:
push:
branches:
- develop
- main
tags:
- "v*.*.*"

jobs:
get-tag:
runs-on: ubuntu-latest
name: Get tag
outputs:
tag: ${{ steps.parse-tag.outputs.tag }}
steps:
- uses: actions/checkout@v3
- uses: aica-technology/.github/.github/actions/docker-tag-from-git@v0.6.1
id: parse-tag

build:
needs: [get-tag]
strategy:
matrix:
arch: [amd64, arm64]
include:
- image: ubuntu-latest
# FIXME: using 4vcpu image because of heavy RAM usage when building pinoccio on arm64
- image: buildjet-4vcpu-ubuntu-2204-arm
arch: arm64

runs-on: ${{ matrix.image }}
name: Build and publish (${{ matrix.arch }})
steps:
- uses: actions/checkout@v3

- uses: aica-technology/.github/.github/actions/list-add-suffixes@v0.6.1
id: merge-tags
with:
list: ${{ needs.get-tag.outputs.tag }}
suffixes: ${{ matrix.arch }}
glue_separator: "-"

- uses: aica-technology/.github/.github/actions/ghcr-build@v0.6.1
with:
image_name: aica-technology/control-libraries
image_tags: ${{ steps.merge-tags.outputs.list }}
dockerfile_path: Dockerfile.ci
token: ${{ secrets.GITHUB_TOKEN }}

multi-arch:
runs-on: ubuntu-latest
name: Merge into a multi-arch image
needs: [get-tag, build]
steps:
- uses: aica-technology/.github/.github/actions/ghcr-manifest-merge@v0.6.1
with:
image_name: aica-technology/control-libraries
image_tags: ${{ needs.get-tag.outputs.tag }}
archs: amd64,arm64
token: ${{ secrets.GITHUB_TOKEN }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ source/build
.clang-format

# protobuf generated bindings
protocol/protobuf/bindings/
protocol/protobuf/bindings/
.DS_Store
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
# CHANGELOG

Release Versions:
- [7.1.0](#710)
- [7.0.0](#700)
- [6.3.1](#631)
- [6.3.0](#630)
- [6.2.0](#620)

## 7.1.0

Version 7.1.0 contains behind-the-scenes structural improvements to the build system and the CI as well as a few
minor improvements and fixes to state_representation.

### Full changelog:

- Update push hooks in build-release.yaml (#127)
- feat(ci): add prebuilt control-libraries image akin to network-interfaces (#125)
- Add overloaded `make_shared_parameter` with no parameter (#123)
- Catch out of range exception in `ParameterMap::assert_parameter_valid` (#122)
- Construct zero matrices in compliant twist controller (#120)

## 7.0.0

Version 7.0.0 is a major update to the `state_representation` module to make `State` types more internally consistent
Expand Down
16 changes: 16 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.15)
project(all_control_libraries)

add_subdirectory(source)
add_subdirectory(protocol/clproto_cpp)

if(BUILD_TESTING)
# reexport the test target defined in the subdirectories
enable_testing()
endif()

# add licenses
install(
DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/licenses"
DESTINATION "share/doc/control-libraries/licenses"
)
129 changes: 129 additions & 0 deletions Dockerfile.ci
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
FROM ghcr.io/aica-technology/ros2-ws:humble as base
FROM base as apt-dependencies
COPY apt-packages.tx[t] /

RUN <<HEREDOC
if [ ! -s /apt-packages.txt ]; then
set +e # FIXME: without this, the script fails because of an issue with `clear_console`
exit 0
fi

mkdir -p /tmp/apt

sudo apt-get update
# We then do a dry-run and parse the output of apt to gather the list of packages to be installed
# Example output:
# ```
# #########
# NOTE: This is only a simulation!
# apt-get needs root privileges for real execution.
# Keep also in mind that locking is deactivated,
# so don't depend on the relevance to the real current situation!
# Reading package lists...
# Building dependency tree...
# Reading state information...
# The following additional packages will be installed:
# libavutil56 libblosc1
# The following NEW packages will be installed:
# libavutil56 libblosc1
# 0 upgraded, 5 newly installed, 0 to remove and 28 not upgraded.
# Inst libavutil56 (7:4.4.2-0ubuntu0.22.04.1 Ubuntu:22.04/jammy-updates, Ubuntu:22.04/jammy-security [arm64])
# Inst libblosc1 (1.21.1+ds2-2 Ubuntu:22.04/jammy [arm64])
# Conf libavutil56 (7:4.4.2-0ubuntu0.22.04.1 Ubuntu:22.04/jammy-updates, Ubuntu:22.04/jammy-security [arm64])
# Conf libblosc1 (1.21.1+ds2-2 Ubuntu:22.04/jammy [arm64])
# ```
# Transformed into:
# ```
# libavutil56
# libblosc1
# ```
xargs -a /apt-packages.txt apt-get install --dry-run \
| grep -e '^Inst ' \
| sed -E 's/^Inst (\S+) .*$/\1/' > /tmp/new-packages.txt
# Then we install apt packages like normal
xargs -a /apt-packages.txt sudo apt-get install -y
# Finally we use dpkg to get all files installed by those packages and copy them to a new root
# - get list of files installed by all the packages
# - remove empty lines
# - sort
# - remove duplicates
# - copy files while keeping file hierarchy and preserving links as-is
# - remove "omitting directory" messages (we don't do recursive copy as we only want specific files) for cleaner output
xargs -a /tmp/new-packages.txt dpkg-query -L \
| sed '/^$/d' | sort | uniq \
| xargs -d "\n" cp --parents -dp -t /tmp/apt 2>&1 \
| grep -v 'omitting directory'
# this root can then be copied to / to install everything globally or use LD_LIBRARY_PATH to use it locally
HEREDOC

FROM base as dep-pinocchio
COPY --from=apt-dependencies /tmp/apt /
ARG PINOCCHIO_TAG=v2.6.9
# FIXME: it would be nicer to have it all in the root CMakelists.txt but:
# * `pinocchio` doesn't provide an include directory we can easily plug into `target_include_directories` and thus needs to be installed first
# * `pinocchio` uses hacks relying on undocumented CMake quirks which break if you use `FetchContent`
# FIXME: it needs `CMAKE_INSTALL_PREFIX` and `--prefix` because it doesn't install to the right place otherwise
RUN \
--mount=type=cache,target=./pinocchio,id=cmake-pinocchio-src-${PINOCCHIO_TAG}-${TARGETPLATFORM},uid=1000 \
--mount=type=cache,target=./build,id=cmake-pinocchio-${PINOCCHIO_TAG}-${TARGETPLATFORM},uid=1000 \
if [ ! -f pinocchio/CMakeLists.txt ]; then rm -rf pinocchio/* && git clone --depth 1 -b ${PINOCCHIO_TAG} --recursive https://github.com/stack-of-tasks/pinocchio; fi \
&& cmake -B build -S pinocchio -DCMAKE_BUILD_TYPE=Release -DBUILD_PYTHON_INTERFACE=OFF -DCMAKE_INSTALL_PREFIX=/tmp/deps \
&& cmake --build build --target all install
# FIXME: pinocchio produces non-portable paths
RUN find /tmp/deps -type f -exec sed -i 's#/tmp/deps#/usr#g' '{}' \;

FROM base as dep-osqp
COPY dependencies/osqp.cmake CMakeLists.txt
RUN \
--mount=type=cache,target=./build,id=cmake-osqp-${TARGETPLATFORM},uid=1000 \
cmake -B build -DCMAKE_BUILD_TYPE=Release \
&& cmake --build build \
&& cmake --install build --prefix /tmp/deps

FROM base as dependencies
# Needed to build `osqp-eigen`
COPY --from=dep-osqp /tmp/deps /usr
COPY dependencies/dependencies.cmake CMakeLists.txt
RUN \
--mount=type=cache,target=./build,id=cmake-deps-${TARGETPLATFORM},uid=1000 \
cmake -B build -DCMAKE_BUILD_TYPE=Release \
&& cmake --build build \
&& cmake --install build --prefix /tmp/deps
COPY --from=dep-osqp /tmp/deps /tmp/deps
COPY --from=dep-pinocchio /tmp/deps /tmp/deps

FROM base as code
WORKDIR /src
COPY --from=apt-dependencies /tmp/apt /
COPY --from=dependencies /tmp/deps /usr
COPY --chown=${USER} . /src

FROM code as build
RUN \
--mount=type=cache,target=./build,id=cmake-${TARGETPLATFORM},uid=1000 \
cmake -B build -DCMAKE_BUILD_TYPE=Release \
&& cmake --build build

FROM build as test
RUN \
--mount=type=cache,target=./build,id=cmake-${TARGETPLATFORM},uid=1000 \
cmake -B build -DBUILD_TESTING=ON \
&& CTEST_OUTPUT_ON_FAILURE=1 cmake --build build --target test

FROM build as install
RUN \
--mount=type=cache,target=./build,id=cmake-${TARGETPLATFORM},uid=1000 \
cmake --install build --prefix /tmp/cl

FROM base as python
COPY --chown=${USER} ./python /python
COPY --from=install /tmp/cl /usr
RUN \
--mount=type=cache,target=${HOME}/.cache,id=pip-${TARGETPLATFORM},uid=1000 \
python3 -m pip install --prefix=/tmp/python /python

FROM scratch
COPY --from=apt-dependencies /tmp/apt /
COPY --from=dependencies /tmp/deps /usr
COPY --from=install /tmp/cl /usr
COPY --from=python /tmp/python/local/lib/python3.10/dist-packages/ /home/ros2/.local/lib/python3.10/site-packages/
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.0.0
7.1.0
2 changes: 2 additions & 0 deletions apt-packages.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
libboost-all-dev
liburdfdom-dev
2 changes: 1 addition & 1 deletion demos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
add_compile_options(-Wall -Wextra -Wpedantic)
endif()

find_package(control_libraries 7.0.0 CONFIG REQUIRED)
find_package(control_libraries 7.1.0 CONFIG REQUIRED)

set(DEMOS_SCRIPTS
task_space_control_loop
Expand Down
21 changes: 21 additions & 0 deletions dependencies/dependencies.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# FIXME: it would be nicer to have it all in the root CMakelists.txt but:
# * `OVERRIDE_FIND_PACKAGE` requires CMake 3.24
# * some `protobuf` includes don't work when using `FetchContent`
cmake_minimum_required(VERSION 3.15)
project(control-libraries-dependencies)

include(FetchContent)
FetchContent_Declare(
OsqpEigen
GIT_REPOSITORY https://github.com/robotology/osqp-eigen.git
GIT_TAG v0.6.4
)

FetchContent_Declare(
protobuf
GIT_REPOSITORY https://github.com/protocolbuffers/protobuf.git
GIT_TAG v3.17.0
SOURCE_SUBDIR cmake
)

FetchContent_MakeAvailable(OsqpEigen protobuf)
14 changes: 14 additions & 0 deletions dependencies/osqp.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# FIXME: it would be nicer to have it all in the root CMakelists.txt but:
# * `OVERRIDE_FIND_PACKAGE` requires CMake 3.24
# * `osqp::osqp` is somehow not working in OSQP-Eigen when built together
cmake_minimum_required(VERSION 3.15)
project(control-libraries-osqp)

include(FetchContent)
FetchContent_Declare(
osqp
GIT_REPOSITORY https://github.com/oxfordcontrol/osqp
GIT_TAG v0.6.2
)

FetchContent_MakeAvailable(osqp)
2 changes: 1 addition & 1 deletion doxygen/doxygen.conf
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "Control Libraries"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = 7.0.0
PROJECT_NUMBER = 7.1.0

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
51 changes: 43 additions & 8 deletions protocol/clproto_cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.15)

project(clproto VERSION 7.0.0)
project(clproto VERSION 7.1.0)

# Default to C99
if(NOT CMAKE_C_STANDARD)
Expand All @@ -26,7 +26,11 @@ endif()

include(FindProtobuf)
find_package(Protobuf 3.17 REQUIRED)
find_package(control_libraries ${PROJECT_VERSION} REQUIRED COMPONENTS state_representation)
if (NOT TARGET state_representation)
# if we can't find the state_representation target, we are the top-level project and need to find it,
# otherwise, we are a subproject and the state_representation target is already available
find_package(control_libraries ${PROJECT_VERSION} REQUIRED COMPONENTS state_representation)
endif()

if(BUILD_TESTING)
enable_testing()
Expand All @@ -46,7 +50,38 @@ add_custom_target(generate_proto_bindings COMMAND make cpp_bindings
WORKING_DIRECTORY ${PROTOBUF_DIR}
)

file(GLOB_RECURSE GENERATED_PROTO_BINDINGS "${PROTOBUF_BINDINGS_DIR}/*.pb.cc" "${PROTOBUF_BINDINGS_DIR}/*.pb.h")
# if we are the top-level project, we assume the protobuf bindings are already built manually by the Makefile,
# otherwise, we built them ourselves in this project
if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
file(GLOB_RECURSE GENERATED_PROTO_BINDINGS "${PROTOBUF_BINDINGS_DIR}/*.pb.cc" "${PROTOBUF_BINDINGS_DIR}/*.pb.h")
else()
# FIXME: unfortunately, protobuf_generate_* is a bit broken, so we do it by hand
set(IMPORT_PATH ${PROTOBUF_DIR}/proto)
file(GLOB_RECURSE PROTO_FILES "${IMPORT_PATH}/*.proto")
set(PROTOBUF_BINDINGS_DIR ${CMAKE_CURRENT_BINARY_DIR}/bindings)

set(GENERATED_PROTO_BINDINGS)
set(PROTO_FILES_TEXT)
foreach(PROTO_FILE ${PROTO_FILES})
string(REPLACE "${IMPORT_PATH}/" "" PROTO_FILE_REL "${PROTO_FILE}")
get_filename_component(PROTO_FILE_PATH ${PROTO_FILE_REL} DIRECTORY)
get_filename_component(PROTO_FILE_NAME ${PROTO_FILE_REL} NAME_WE)
list(APPEND GENERATED_PROTO_BINDINGS "${PROTOBUF_BINDINGS_DIR}/${PROTO_FILE_PATH}/${PROTO_FILE_NAME}.pb.cc")
list(APPEND GENERATED_PROTO_BINDINGS "${PROTOBUF_BINDINGS_DIR}/${PROTO_FILE_PATH}/${PROTO_FILE_NAME}.pb.h")
list(APPEND PROTO_FILES_TEXT ${PROTO_FILE_REL})
endforeach()
string(REPLACE ";" ", " PROTO_FILES_TEXT "${PROTO_FILES_TEXT}")

make_directory(${PROTOBUF_BINDINGS_DIR})
add_custom_command(
OUTPUT ${GENERATED_PROTO_BINDINGS}
COMMAND protobuf::protoc
ARGS --cpp_out ${PROTOBUF_BINDINGS_DIR} -I${IMPORT_PATH} ${PROTO_FILES}
DEPENDS ${PROTOBUF_BINDINGS_DIR} ${PROTO_FILES} protobuf::protoc
COMMENT "Running C++ protocol buffer compiler on ${PROTO_FILES_TEXT}"
VERBATIM
)
endif()

add_library(${PROJECT_NAME}_bindings STATIC ${GENERATED_PROTO_BINDINGS})
target_include_directories(${PROJECT_NAME}_bindings PUBLIC ${PROTOBUF_BINDINGS_DIR})
Expand All @@ -63,7 +98,7 @@ target_include_directories(${PROJECT_NAME}
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
)
set_target_properties(${PROJECT_NAME} PROPERTIES PUBLIC_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/include/clproto.hpp)
target_link_libraries(${PROJECT_NAME} PUBLIC ${PROTOBUF_LIBRARY} state_representation PRIVATE ${PROJECT_NAME}_bindings)
target_link_libraries(${PROJECT_NAME} PUBLIC protobuf::libprotobuf state_representation PRIVATE ${PROJECT_NAME}_bindings)

# install the target and create export-set
install(TARGETS ${PROJECT_NAME}
Expand Down Expand Up @@ -122,10 +157,10 @@ install(FILES
if(${PKG_CONFIG_FOUND})
set(PKG_NAME ${CMAKE_PROJECT_NAME})
set(PKG_DESC "This library provides a simple interface for encoding and decoding control library type objects to and from a serialized binary string representation (the wire format).")
set(PKG_EXTERNAL_DEPS "state_representation >= ${CMAKE_PROJECT_VERSION}")
set(PKG_EXTERNAL_DEPS "state_representation >= ${PROJECT_VERSION}")
set(PKG_CFLAGS "-lprotobuf")
set(pkg_conf_file "clproto.pc")
configure_file("${CMAKE_SOURCE_DIR}/${pkg_conf_file}.in" "${CMAKE_BINARY_DIR}/${pkg_conf_file}" @ONLY)
install(FILES "${CMAKE_BINARY_DIR}/${pkg_conf_file}"
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${pkg_conf_file}.in" "${CMAKE_CURRENT_BINARY_DIR}/${pkg_conf_file}" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${pkg_conf_file}"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig/ COMPONENT pkgconfig)
endif()
endif()
Loading

0 comments on commit 7da0c99

Please sign in to comment.