From 01254a69c4ab973424e15f036c6bebecf2b09362 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Thu, 3 Dec 2020 17:08:46 -0800 Subject: [PATCH 1/3] Update build instructions in README and CI * Cherry-pick upstream ros2-java/ros2_java#119 - Updates build instructions in README - Update CI for desktop - Add CI for Android - Minor patches to code for Android * Switch to latest release of ros-tooling GitHub actions. --- .github/workflows/build_and_test.yml | 68 +++++- README.md | 224 +++++++++--------- .../java/org/ros2/rcljava/node/NodeImpl.java | 2 - .../org/ros2/rcljava/client/ClientTest.java | 14 +- .../java/org/ros2/rcljava/node/NodeTest.java | 13 + .../parameters/AsyncParametersClientTest.java | 14 +- .../parameters/SyncParametersClientTest.java | 14 +- ros2_java_android.repos | 102 +++++++- rosidl_generator_java/resource/msg.cpp.em | 10 +- .../org/ros2/generator/InterfacesTest.java | 14 +- 10 files changed, 336 insertions(+), 139 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index f93ed61f..3237cb72 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -11,7 +11,7 @@ jobs: sudo apt update -qq sudo apt install -y default-jdk - uses: actions/checkout@v2 - - uses: ros-tooling/setup-ros@master # using master, until a released version supports rolling + - uses: ros-tooling/setup-ros@0.1.0 with: required-ros-distributions: rolling - uses: ros-tooling/action-ros-ci@master @@ -19,3 +19,69 @@ jobs: package-name: rosidl_generator_java rcljava_common rcljava target-ros2-distro: rolling vcs-repo-file-url: ${{ github.workspace }}/ros2_java_desktop.repos + + build_android: + runs-on: ubuntu-18.04 + steps: + - name: Install Java + run: | + sudo apt-get update -qq + sudo apt-get install -y default-jdk gradle + - uses: actions/checkout@v2 + - name: Setup locale for ROS 2 + run: | + sudo locale-gen en_US en_US.UTF-8 + sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 + export LANG=en_US.UTF-8 + - name: Setup sources for ROS 2 + run: | + sudo apt-get update && sudo apt-get install -y curl gnupg2 lsb-release + curl -sL https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - + sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' + - name: Install ROS 2 dependencies + run: | + sudo apt-get update && sudo apt-get install -y python3-colcon-common-extensions python3-vcstool python3-lark-parser python3-dev + - name: Install colcon extensions for Gradle + run: | + sudo pip3 install git+git://github.com/colcon/colcon-gradle.git + sudo pip3 install git+git://github.com/colcon/colcon-ros-gradle.git + - name: Install Android NDK + run: | + curl -LO https://dl.google.com/android/repository/android-ndk-r21d-linux-x86_64.zip + unzip android-ndk-r21d-linux-x86_64.zip + - name: Setup workspace with VCS repo file + run: | + mkdir -p ros2_java_ws/src + cd ros2_java_ws + curl -sL file://${{ github.workspace }}/ros2_java_android.repos | vcs import src + # Use checked out version of ros2_java + rm -rf src/ros2_java/ros2_java + ln --symbolic ${{ github.workspace }} src/ros2_java + - name: Build ros2_java for Android + run: | + export PYTHON3_EXEC="$( which python3 )" + export PYTHON3_LIBRARY="$( ${PYTHON3_EXEC} -c 'import os.path; from distutils import sysconfig; print(os.path.realpath(os.path.join(sysconfig.get_config_var("LIBPL"), sysconfig.get_config_var("LDLIBRARY"))))' )" + export PYTHON3_INCLUDE_DIR="$( ${PYTHON3_EXEC} -c 'from distutils import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))' )" + export ANDROID_ABI=armeabi-v7a + export ANDROID_NATIVE_API_LEVEL=android-21 + export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang + export ANDROID_NDK=${PWD}/android-ndk-r21d + + cd ros2_java_ws + colcon build \ + --packages-ignore cyclonedds rcl_logging_log4cxx rosidl_generator_py \ + --packages-up-to rcljava \ + --cmake-args \ + -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} \ + -DPYTHON_LIBRARY=${PYTHON3_LIBRARY} \ + -DPYTHON_INCLUDE_DIR=${PYTHON3_INCLUDE_DIR} \ + -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ + -DANDROID_FUNCTION_LEVEL_LINKING=OFF \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \ + -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \ + -DANDROID_STL=c++_shared \ + -DANDROID_ABI=${ANDROID_ABI} \ + -DANDROID_NDK=${ANDROID_NDK} \ + -DTHIRDPARTY=ON \ + -DCOMPILE_EXAMPLES=OFF \ + -DCMAKE_FIND_ROOT_PATH="${PWD}/install" diff --git a/README.md b/README.md index 99ed10c8..20787538 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,31 @@ -ROS2 for Java -============= +# ROS 2 Java client library -Build status ------------- +### Build status -| Target | Status | -|----------|--------| -| **Ubuntu Xenial (OpenJDK)** | [![Build Status](http://vsts-matrix-badges.herokuapp.com/repos/ros2-java/ros2-java/1/branches/master/1)](https://dev.azure.com/ros2-java/ros2-java/_build?definitionId=1) | -| **Ubuntu Xenial (Android)** | [![Build Status](http://vsts-matrix-badges.herokuapp.com/repos/ros2-java/ros2-java/1/branches/master/2)](https://dev.azure.com/ros2-java/ros2-java/_build?definitionId=1) | +| Target | Status | +|-------------------------------------------|---------------| +| **ROS Dashing - Ubuntu Bionic (OpenJDK)** | ![Build Status](https://github.com/ros2-java/ros2_java/workflows/CI/badge.svg?branch=dashing) | -Introduction ------------- +## Introduction -This is a set of projects (bindings, code generator, examples and more) that enables developers to write ROS2 +This is a set of projects (bindings, code generator, examples and more) that enables developers to write ROS 2 applications for the JVM and Android. Besides this repository itself, there's also: -- https://github.com/esteve/ament_java, which adds support for Gradle to Ament -- https://github.com/esteve/ament_gradle_plugin, a Gradle plugin that makes it easier to use ROS2 in Java and Android project. The Gradle plugin can be installed from Gradle Central https://plugins.gradle.org/plugin/org.ros2.tools.gradle -- https://github.com/esteve/ros2_java_examples, examples for the Java Runtime Environment -- https://github.com/esteve/ros2_android_examples, examples for Android +- https://github.com/ros2-java/ament_java, which adds support for Gradle to Ament +- https://github.com/ros2-java/ament_gradle_plugin, a Gradle plugin that makes it easier to use ROS 2 in Java and Android project. The Gradle plugin can be installed from Gradle Central https://plugins.gradle.org/plugin/org.ros2.tools.gradle +- https://github.com/ros2-java/ros2_java_examples, examples for the Java Runtime Environment +- https://github.com/ros2-java/ros2_android_examples, examples for Android -Is this Java only? ------------------- +### Is this Java only? -No, any language that targets the JVM can be used to write ROS2 applications. +No, any language that targets the JVM can be used to write ROS 2 applications. -Including Android? ------------------- +### Including Android? Yep! Make sure to use Fast-RTPS as your DDS vendor and at least [this revision](https://github.com/eProsima/Fast-RTPS/commit/5301ef203d45528a083821c3ba582164d782360b). -Features --------- +### Features The current set of features include: - Generation of all builtin and complex ROS types, including arrays, strings, nested types, constants, etc. @@ -41,76 +34,80 @@ The current set of features include: - Clients and services - Timers - Composition (i.e. more than one node per process) -- Time handling (system and steady, ROS time not yet supported https://github.com/ros2/ros2/issues/350) +- Time handling (system and steady, ROS time not yet supported https://github.com/ros2-java/ros2_java/issues/122) - Support for Android - Parameters services and clients (both asynchronous and synchronous) -Sounds great, how can I try this out? -------------------------------------- +## Sounds great, how can I try this out? + +### Install dependencies > Note: While the following instructions use a Linux shell the same can be done on other platforms like Windows with slightly adjusted commands. -> -> For Windows and Mac, first follow the steps for installing prerequisites on the binary installation page: https://github.com/ros2/ros2/wiki/Installation -> -> Stop and return here when you reach the "Downloading ROS 2" section. -Download the ament repositories in a separate workspace: +1. [Install ROS 2](https://index.ros.org/doc/ros2/Installation). + +1. Install Java and a JDK. + + On Ubuntu, you can install OpenJDK with: + + sudo apt install default-jdk + +1. Install Gradle. +Make sure you have Gradle 3.2 (or later) installed. + + *Ubuntu Bionic or later* + + sudo apt install gradle + + *macOS* + + brew install gradle + + Note: if run into compatibily issues between gradle 3.x and Java 9, try using Java 8, + + brew tap caskroom/versions + brew cask install java8 + export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.8.0.jdk/Contents/Home + + *Windows* + + choco install gradle + +1. Install build tools: + + sudo apt install curl python3-colcon-common-extensions python3-pip python3-vcstool -``` -mkdir -p ament_ws/src -cd ament_ws -curl -skL https://raw.githubusercontent.com/esteve/ament_java/master/ament_java.repos -o ament_java.repos -vcs import src < ament_java.repos -src/ament/ament_tools/scripts/ament.py build --symlink-install --isolated -``` +1. Install Gradle extensions for colcon: -> Note: On Windows, use `python src/ament/ament_tools/scripts/ament.py build`, as `*.py` scripts must be prefixed with `python`, `--symlink-install` is not supported due to a bug in Python symlinks, and `--isolated` creates paths that are too long. -> Additionally, you may need to call `call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvars64.bat"` if you have not run from a VS 2017 terminal. + python3 -m pip install -U git+https://github.com/colcon/colcon-gradle + python3 -m pip install --no-deps -U git+https://github.com/colcon/colcon-ros-gradle -We need to split the build process between Ament and the rest of `ros2_java` workspace so that the additional build type for Gradle projects is picked up by Ament. +### Download and Build ROS 2 Java for Desktop -Make sure you have Gradle 3.2 (or later) installed. Ubuntu 16.04 ships with Gradle 2.10, you can install a more recent version of Gradle from the following PPA: +1. Source your ROS 2 installation, for example: -``` -$ sudo add-apt-repository ppa:cwchien/gradle -$ sudo apt install -y gradle -``` -For OSX, use homebrew command to install gradle: + source /opt/ros/dashing/setup.bash -``` -$ brew install gradle -``` +1. Download the ROS 2 Java repositories into a workspace: -For OSX users, there some compatibily issues have been reported between gradle 3.x and Java 9. Currently only the combination of Gradle 3.x + Java 8 has been tested successfully. Make sure to use install and use Java 8 for the building process: + mkdir -p ros2_java_ws/src + cd ros2_java_ws + curl -skL https://raw.githubusercontent.com/ros2-java/ros2_java/dashing/ros2_java_desktop.repos | vcs import src -``` -$ brew tap caskroom/versions -$ brew cask install java8 -$ export JAVA_HOME=/Library/Java/JavaVirtualMachines/1.8.0.jdk/Contents/Home -``` +1. **Linux only** Install ROS dependencies: -> Note: On Windows, you may use `choco install -y gradle` + rosdep install --from-paths src -y -i --skip-keys "ament_tools" -The following sections deal with building the `ros2_java` codebase for the desktop Java runtime and for Android. +1. Build desktop packages: -Desktop -------- + colcon build --symlink-install -``` -mkdir -p ros2_java_ws/src -cd ros2_java_ws -curl -skL https://raw.githubusercontent.com/esteve/ros2_java/master/ros2_java_desktop.repos -o ros2_java_desktop.repos -vcs import src < ros2_java_desktop.repos -. ../ament_ws/install_isolated/local_setup.sh -ament build --symlink-install --isolated -``` + *Note, on Windows we have to use `--merge-install`* -> On Windows, if you would like to use OpenSplice, call `call "C:\opensplice67\HDE\x86_64.win64\release.bat"` before building. + colcon build --merge-install -Now you can just run a bunch of examples, head over to https://github.com/esteve/ros2_java_examples for more information. -Android -------- +### Download and Build ROS 2 Java for Android The Android setup is slightly more complex, you'll need the SDK and NDK installed, and an Android device where you can run the examples. @@ -122,48 +119,43 @@ We'll also need to have the [Android SDK](https://developer.android.com/studio/# Although the `ros2_java_android.repos` file contains all the repositories for the Android bindings to compile, we'll have to disable certain packages (`python_cmake_module`, `rosidl_generator_py`, `test_msgs`) that are included the repositories and that we either don't need or can't cross-compile properly (e.g. the Python generator) -``` -# define paths -ROOT_DIR = ${HOME} -AMENT_WORKSPACE=${ROOT_DIR}/ament_ws -ROS2_ANDROID_WORKSPACE=${ROOT_DIR}/ros2_android_ws - -# pull and build ament -mkdir -p ${AMENT_WORKSPACE}/src -cd ${AMENT_WORKSPACE} -wget https://raw.githubusercontent.com/esteve/ament_java/master/ament_java.repos -vcs import ${AMENT_WORKSPACE}/src < ament_java.repos -src/ament/ament_tools/scripts/ament.py build --symlink-install --isolated - -# android build configuration -export PYTHON3_EXEC="$( which python3 )" -export ANDROID_ABI=armeabi-v7a -export ANDROID_NATIVE_API_LEVEL=android-21 -export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang - -# pull and build ros2 for android -mkdir -p ${ROS2_ANDROID_WORKSPACE}/src -cd ${ROS2_ANDROID_WORKSPACE} -wget https://raw.githubusercontent.com/esteve/ros2_java/master/ros2_java_android.repos -vcs import ${ROS2_ANDROID_WORKSPACE}/src < ros2_java_android.repos -source ${AMENT_WORKSPACE}/install_isolated/local_setup.sh -ament build --isolated --skip-packages test_msgs \ - --cmake-args \ - -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} \ - -DCMAKE_TOOLCHAIN_FILE=$ANDROID_NDK/build/cmake/android.toolchain.cmake \ - -DANDROID_FUNCTION_LEVEL_LINKING=OFF \ - -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \ - -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \ - -DANDROID_STL=gnustl_shared \ - -DANDROID_ABI=${ANDROID_ABI} \ - -DANDROID_NDK=${ANDROID_NDK} \ - -DTHIRDPARTY=ON \ - -DCOMPILE_EXAMPLES=OFF \ - -DCMAKE_FIND_ROOT_PATH="$AMENT_WORKSPACE/install_isolated;$ROS2_ANDROID_WORKSPACE/install_isolated" \ - -- \ - --parallel \ - --ament-gradle-args \ - -Pament.android_stl=gnustl_shared -Pament.android_abi=$ANDROID_ABI -Pament.android_ndk=$ANDROID_NDK -- -``` - -You can find more information about the Android examples at https://github.com/esteve/ros2_android_examples +1. Download the [Android NDK](https://developer.android.com/ndk/downloads/index.html) and set the environment variable `ANDROID_NDK` to the path where it is extracted. + +1. Download the [Android SDK](https://developer.android.com/studio/#downloads) and set the environment variable `ANDROID_HOME` to the path where it is extracted. + +1. Clone ROS 2 and ROS 2 Java source code: + + mkdir -p $HOME/ros2_android_ws/src + cd $HOME/ros2_android_ws + curl https://raw.githubusercontent.com/ros2-java/ros2_java/dashing/ros2_java_android.repos | vcs import src + +1. Set Android build configuration: + + export PYTHON3_EXEC="$( which python3 )" + export PYTHON3_LIBRARY="$( ${PYTHON3_EXEC} -c 'import os.path; from distutils import sysconfig; print(os.path.realpath(os.path.join(sysconfig.get_config_var("LIBPL"), sysconfig.get_config_var("LDLIBRARY"))))' )" + export PYTHON3_INCLUDE_DIR="$( ${PYTHON3_EXEC} -c 'from distutils import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))' )" + export ANDROID_ABI=armeabi-v7a + export ANDROID_NATIVE_API_LEVEL=android-21 + export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang + +1. Build (skipping packages that we don't need or can't cross-compile): + + colcon build \ + --packages-ignore cyclonedds rcl_logging_log4cxx rosidl_generator_py \ + --packages-up-to rcljava \ + --cmake-args \ + -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} \ + -DPYTHON_LIBRARY=${PYTHON3_LIBRARY} \ + -DPYTHON_INCLUDE_DIR=${PYTHON3_INCLUDE_DIR} \ + -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ + -DANDROID_FUNCTION_LEVEL_LINKING=OFF \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \ + -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \ + -DANDROID_STL=c++_shared \ + -DANDROID_ABI=${ANDROID_ABI} \ + -DANDROID_NDK=${ANDROID_NDK} \ + -DTHIRDPARTY=ON \ + -DCOMPILE_EXAMPLES=OFF \ + -DCMAKE_FIND_ROOT_PATH="${PWD}/install" + +You can find more information about the Android examples at https://github.com/ros2-java/ros2_android_examples diff --git a/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java b/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java index 5c11aed8..1527c020 100644 --- a/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java +++ b/rcljava/src/main/java/org/ros2/rcljava/node/NodeImpl.java @@ -60,8 +60,6 @@ import java.lang.ref.WeakReference; -import java.lang.reflect.Method; - import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; diff --git a/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java b/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java index df7d2a6c..f2961e5a 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/client/ClientTest.java @@ -26,6 +26,7 @@ import org.junit.Test; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; import java.time.Duration; import java.util.Arrays; @@ -46,7 +47,18 @@ public class ClientTest { @BeforeClass public static void setupOnce() throws Exception { RCLJava.rclJavaInit(); - org.apache.log4j.BasicConfigurator.configure(); + try + { + // Configure log4j. Doing this dynamically so that Android does not complain about missing + // the log4j JARs, SLF4J uses Android's native logging mechanism instead. + Class c = Class.forName("org.apache.log4j.BasicConfigurator"); + Method m = c.getDeclaredMethod("configure", (Class[]) null); + Object o = m.invoke(null, (Object[]) null); + } + catch (Exception e) + { + e.printStackTrace(); + } } public class TestClientConsumer implements TriConsumer[]) null); + Object o = m.invoke(null, (Object[]) null); + } + catch (Exception e) + { + e.printStackTrace(); + } } public class TestConsumer implements Consumer { diff --git a/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java b/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java index 5bd52bc9..c0ce876a 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/parameters/AsyncParametersClientTest.java @@ -26,6 +26,7 @@ import org.junit.Test; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -70,7 +71,18 @@ public TestConsumer(RCLFuture resultFuture) { @BeforeClass public static void setupOnce() throws Exception { RCLJava.rclJavaInit(); - org.apache.log4j.BasicConfigurator.configure(); + try + { + // Configure log4j. Doing this dynamically so that Android does not complain about missing + // the log4j JARs, SLF4J uses Android's native logging mechanism instead. + Class c = Class.forName("org.apache.log4j.BasicConfigurator"); + Method m = c.getDeclaredMethod("configure", (Class[]) null); + Object o = m.invoke(null, (Object[]) null); + } + catch (Exception e) + { + e.printStackTrace(); + } } @Before diff --git a/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java b/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java index 8248f1dd..d44c566a 100644 --- a/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java +++ b/rcljava/src/test/java/org/ros2/rcljava/parameters/SyncParametersClientTest.java @@ -26,6 +26,7 @@ import org.junit.Test; import java.lang.ref.WeakReference; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -53,7 +54,18 @@ public class SyncParametersClientTest { @BeforeClass public static void setupOnce() throws Exception { RCLJava.rclJavaInit(); - org.apache.log4j.BasicConfigurator.configure(); + try + { + // Configure log4j. Doing this dynamically so that Android does not complain about missing + // the log4j JARs, SLF4J uses Android's native logging mechanism instead. + Class c = Class.forName("org.apache.log4j.BasicConfigurator"); + Method m = c.getDeclaredMethod("configure", (Class[]) null); + Object o = m.invoke(null, (Object[]) null); + } + catch (Exception e) + { + e.printStackTrace(); + } } @Before diff --git a/ros2_java_android.repos b/ros2_java_android.repos index f6b76ae2..e1dd0920 100644 --- a/ros2_java_android.repos +++ b/ros2_java_android.repos @@ -1,19 +1,51 @@ repositories: + ament/ament_cmake: + type: git + url: https://github.com/ament/ament_cmake.git + version: dashing + ament/ament_index: + type: git + url: https://github.com/ament/ament_index.git + version: dashing + ament/ament_lint: + type: git + url: https://github.com/ament/ament_lint.git + version: dashing + ament/ament_package: + type: git + url: https://github.com/ament/ament_package.git + version: dashing + ament/googletest: + type: git + url: https://github.com/ament/googletest.git + version: dashing + ament/uncrustify_vendor: + type: git + url: https://github.com/ament/uncrustify_vendor.git + version: dashing + ament/ament_java: + type: git + url: https://github.com/ros2-java/ament_java.git + version: master eProsima/Fast-CDR: type: git url: https://github.com/eProsima/Fast-CDR.git version: v1.0.11 - eProsima/Fast-RTPS: + eProsima/Fast-DDS: type: git - url: https://github.com/eProsima/Fast-RTPS.git + url: https://github.com/eProsima/Fast-DDS.git version: v1.8.2 - ros2/ament_cmake_ros: + osrf/osrf_pycommon: type: git - url: https://github.com/ros2/ament_cmake_ros.git + url: https://github.com/osrf/osrf_pycommon.git version: dashing - ros2/rcutils: + osrf/osrf_testing_tools_cpp: type: git - url: https://github.com/ros2/rcutils.git + url: https://github.com/ros2-java/osrf_testing_tools_cpp.git + version: dashing-android + ros2/ament_cmake_ros: + type: git + url: https://github.com/ros2/ament_cmake_ros.git version: dashing ros2/common_interfaces: type: git @@ -23,9 +55,9 @@ repositories: type: git url: https://github.com/ros2/example_interfaces.git version: dashing - ros2/libyaml_vendor: + ros2/launch: type: git - url: https://github.com/ros2/libyaml_vendor.git + url: https://github.com/ros2/launch.git version: dashing ros2/poco_vendor: type: git @@ -39,10 +71,30 @@ repositories: type: git url: https://github.com/ros2/rcl_interfaces.git version: dashing + ros2/rcl_logging: + type: git + url: https://github.com/ros2/rcl_logging.git + version: dashing + ros2/rcpputils: + type: git + url: https://github.com/ros2/rcpputils.git + version: dashing + ros2/rcutils: + type: git + url: https://github.com/ros2/rcutils.git + version: dashing ros2/rmw: type: git url: https://github.com/ros2/rmw.git version: dashing + ros2/rmw_connext: + type: git + url: https://github.com/ros2/rmw_connext.git + version: dashing + ros2/rmw_cyclonedds: + type: git + url: https://github.com/ros2/rmw_cyclonedds.git + version: dashing-eloquent ros2/rmw_fastrtps: type: git url: https://github.com/ros2/rmw_fastrtps.git @@ -51,6 +103,10 @@ repositories: type: git url: https://github.com/ros2/rmw_implementation.git version: dashing + ros2/rmw_opensplice: + type: git + url: https://github.com/ros2/rmw_opensplice.git + version: dashing ros2/rosidl: type: git url: https://github.com/ros2/rosidl.git @@ -63,13 +119,37 @@ repositories: type: git url: https://github.com/ros2/rosidl_defaults.git version: dashing + ros2/rosidl_python: + type: git + url: https://github.com/ros2/rosidl_python.git + version: dashing ros2/rosidl_typesupport: type: git url: https://github.com/ros2/rosidl_typesupport.git version: dashing - ros2/osrf_testing_tools_cpp: + ros2/rosidl_typesupport_connext: + type: git + url: https://github.com/ros2/rosidl_typesupport_connext.git + version: dashing + ros2/rosidl_typesupport_fastrtps: + type: git + url: https://github.com/ros2/rosidl_typesupport_fastrtps.git + version: dashing + ros2/rosidl_typesupport_opensplice: + type: git + url: https://github.com/ros2/rosidl_typesupport_opensplice.git + version: dashing + ros2/test_interface_files: + type: git + url: https://github.com/ros2/test_interface_files.git + version: dashing + ros2/tinydir_vendor: + type: git + url: https://github.com/ros2/tinydir_vendor.git + version: dashing + ros2/unique_identifier_msgs: type: git - url: https://github.com/osrf/osrf_testing_tools_cpp + url: https://github.com/ros2/unique_identifier_msgs.git version: dashing ros2_java/ros2_java: type: git @@ -77,7 +157,7 @@ repositories: version: dashing ros2_java/ros2_android: type: git - url: https://github.com/esteve/ros2_android.git + url: https://github.com/ros2-java/ros2_android.git version: master ros2_java/ros2_android_examples: type: git diff --git a/rosidl_generator_java/resource/msg.cpp.em b/rosidl_generator_java/resource/msg.cpp.em index 9458b285..7b738219 100644 --- a/rosidl_generator_java/resource/msg.cpp.em +++ b/rosidl_generator_java/resource/msg.cpp.em @@ -212,7 +212,7 @@ JNIEXPORT jlong JNICALL Java_@(underscore_separated_jni_type_name)_getDestructor JNIEnv * env = nullptr; // TODO(esteve): check return status assert(g_vm != nullptr); - g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8); + g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); assert(env != nullptr); if (ros_message == nullptr) { @@ -341,7 +341,7 @@ jobject @(underscore_separated_type_name)__convert_to_java(@(msg_normalized_type JNIEnv * env = nullptr; // TODO(esteve): check return status assert(g_vm != nullptr); - g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8); + g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6); assert(env != nullptr); if (_jmessage_obj == nullptr) { @@ -445,7 +445,7 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM * vm, void *) } JNIEnv * env; - if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8) != JNI_OK) { + if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK) { return JNI_ERR; } else { @[for normalized_type, jni_type in cache.items()]@ @@ -494,7 +494,7 @@ if value_method: @[ end if]@ @[end for]@ } - return JNI_VERSION_1_8; + return JNI_VERSION_1_6; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM * vm, void *) @@ -503,7 +503,7 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM * vm, void *) assert(g_vm == vm); JNIEnv * env; - if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_8) == JNI_OK) { + if (g_vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) == JNI_OK) { @[for normalized_type, jni_type in cache.items()]@ if (_j@(normalized_type)_class_global != nullptr) { env->DeleteGlobalRef(_j@(normalized_type)_class_global); diff --git a/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java b/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java index 00638e09..d64af3eb 100644 --- a/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java +++ b/rosidl_generator_java/src/test/java/org/ros2/generator/InterfacesTest.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import java.lang.reflect.Method; import java.util.concurrent.Callable; import java.util.Arrays; import java.util.List; @@ -30,7 +31,18 @@ public class InterfacesTest { @BeforeClass public static void setupOnce() { - org.apache.log4j.BasicConfigurator.configure(); + try + { + // Configure log4j. Doing this dynamically so that Android does not complain about missing + // the log4j JARs, SLF4J uses Android's native logging mechanism instead. + Class c = Class.forName("org.apache.log4j.BasicConfigurator"); + Method m = c.getDeclaredMethod("configure", (Class[]) null); + Object o = m.invoke(null, (Object[]) null); + } + catch (Exception e) + { + e.printStackTrace(); + } } @Rule public ExpectedException thrown = ExpectedException.none(); From f94a6237d8426e7256daaf81bb8bcf5d63aa4fb6 Mon Sep 17 00:00:00 2001 From: pluris Date: Wed, 9 Dec 2020 04:29:33 +0900 Subject: [PATCH 2/3] change code order(methodId 'add' in for loop) (#148) --- rosidl_generator_java/resource/msg.cpp.em | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/rosidl_generator_java/resource/msg.cpp.em b/rosidl_generator_java/resource/msg.cpp.em index 7b738219..a7008a53 100644 --- a/rosidl_generator_java/resource/msg.cpp.em +++ b/rosidl_generator_java/resource/msg.cpp.em @@ -355,6 +355,8 @@ normalized_type = get_normalized_type(member.type) @[ if isinstance(member.type.value_type, (BasicType, AbstractGenericString))]@ auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "L@(list_jni_type);"); jobject _jarray_list_@(member.name)_obj = env->NewObject(_j@(array_list_normalized_type)_class_global, _j@(array_list_normalized_type)_constructor_global); + // TODO(esteve): replace ArrayList with a jobjectArray to initialize the array beforehand + jmethodID _jlist_@(member.name)_add_mid = env->GetMethodID(_j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z"); @[ if isinstance(member.type, Array)]@ for (size_t i = 0; i < @(member.type.size); ++i) { auto _ros_@(member.name)_element = _ros_message->@(member.name)[i]; @@ -375,9 +377,6 @@ normalized_type = get_normalized_type(member.type) jobject _jlist_@(member.name)_element = env->NewObject( _j@(normalized_type)_class_global, _j@(normalized_type)_constructor_global, _ros_@(member.name)_element); @[ end if]@ - // TODO(esteve): replace ArrayList with a jobjectArray to initialize the array beforehand - jmethodID _jlist_@(member.name)_add_mid = env->GetMethodID( - _j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z"); if (_jlist_@(member.name)_element != nullptr) { jboolean _jlist_@(member.name)_add_result = env->CallBooleanMethod(_jarray_list_@(member.name)_obj, _jlist_@(member.name)_add_mid, _jlist_@(member.name)_element); assert(_jlist_@(member.name)_add_result); @@ -387,6 +386,8 @@ normalized_type = get_normalized_type(member.type) auto _jfield_@(member.name)_fid = env->GetFieldID(_j@(msg_normalized_type)_class_global, "@(member.name)", "L@(list_jni_type);"); jobject _jarray_list_@(member.name)_obj = env->NewObject(_j@(array_list_normalized_type)_class_global, _j@(array_list_normalized_type)_constructor_global); + // TODO(esteve): replace ArrayList with a jobjectArray to initialize the array beforehand + jmethodID _jlist_@(member.name)_add_mid = env->GetMethodID(_j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z"); @[ if isinstance(member.type, Array)]@ for (size_t i = 0; i < @(member.type.size); ++i) { @@ -395,8 +396,6 @@ normalized_type = get_normalized_type(member.type) for (size_t i = 0; i < _ros_message->@(member.name).size; ++i) { jobject _jlist_@(member.name)_element = _j@(normalized_type)_to_java_function(&(_ros_message->@(member.name).data[i]), nullptr); @[ end if]@ - // TODO(esteve): replace ArrayList with a jobjectArray to initialize the array beforehand - jmethodID _jlist_@(member.name)_add_mid = env->GetMethodID(_j@(array_list_normalized_type)_class_global, "add", "(Ljava/lang/Object;)Z"); if (_jlist_@(member.name)_element != nullptr) { jboolean _jlist_@(member.name)_add_result = env->CallBooleanMethod(_jarray_list_@(member.name)_obj, _jlist_@(member.name)_add_mid, _jlist_@(member.name)_element); assert(_jlist_@(member.name)_add_result); From f09b1b757fd67e033ce23091da12b53184a23ff4 Mon Sep 17 00:00:00 2001 From: Jacob Perron Date: Wed, 23 Dec 2020 15:00:11 -0800 Subject: [PATCH 3/3] Disable android CI Building all of ROS 2 from source does not work. It appears there may be something wrong with the dependency tree and/or integration with the rosidl pipeline. For some reason, if we only build interface packages from source (like we do in desktop CI) there are no issues. Signed-off-by: Jacob Perron --- .github/workflows/build_and_test.yml | 130 +++++++++++++-------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/.github/workflows/build_and_test.yml b/.github/workflows/build_and_test.yml index 3237cb72..88dd5618 100644 --- a/.github/workflows/build_and_test.yml +++ b/.github/workflows/build_and_test.yml @@ -20,68 +20,68 @@ jobs: target-ros2-distro: rolling vcs-repo-file-url: ${{ github.workspace }}/ros2_java_desktop.repos - build_android: - runs-on: ubuntu-18.04 - steps: - - name: Install Java - run: | - sudo apt-get update -qq - sudo apt-get install -y default-jdk gradle - - uses: actions/checkout@v2 - - name: Setup locale for ROS 2 - run: | - sudo locale-gen en_US en_US.UTF-8 - sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 - export LANG=en_US.UTF-8 - - name: Setup sources for ROS 2 - run: | - sudo apt-get update && sudo apt-get install -y curl gnupg2 lsb-release - curl -sL https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - - sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' - - name: Install ROS 2 dependencies - run: | - sudo apt-get update && sudo apt-get install -y python3-colcon-common-extensions python3-vcstool python3-lark-parser python3-dev - - name: Install colcon extensions for Gradle - run: | - sudo pip3 install git+git://github.com/colcon/colcon-gradle.git - sudo pip3 install git+git://github.com/colcon/colcon-ros-gradle.git - - name: Install Android NDK - run: | - curl -LO https://dl.google.com/android/repository/android-ndk-r21d-linux-x86_64.zip - unzip android-ndk-r21d-linux-x86_64.zip - - name: Setup workspace with VCS repo file - run: | - mkdir -p ros2_java_ws/src - cd ros2_java_ws - curl -sL file://${{ github.workspace }}/ros2_java_android.repos | vcs import src - # Use checked out version of ros2_java - rm -rf src/ros2_java/ros2_java - ln --symbolic ${{ github.workspace }} src/ros2_java - - name: Build ros2_java for Android - run: | - export PYTHON3_EXEC="$( which python3 )" - export PYTHON3_LIBRARY="$( ${PYTHON3_EXEC} -c 'import os.path; from distutils import sysconfig; print(os.path.realpath(os.path.join(sysconfig.get_config_var("LIBPL"), sysconfig.get_config_var("LDLIBRARY"))))' )" - export PYTHON3_INCLUDE_DIR="$( ${PYTHON3_EXEC} -c 'from distutils import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))' )" - export ANDROID_ABI=armeabi-v7a - export ANDROID_NATIVE_API_LEVEL=android-21 - export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang - export ANDROID_NDK=${PWD}/android-ndk-r21d - - cd ros2_java_ws - colcon build \ - --packages-ignore cyclonedds rcl_logging_log4cxx rosidl_generator_py \ - --packages-up-to rcljava \ - --cmake-args \ - -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} \ - -DPYTHON_LIBRARY=${PYTHON3_LIBRARY} \ - -DPYTHON_INCLUDE_DIR=${PYTHON3_INCLUDE_DIR} \ - -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ - -DANDROID_FUNCTION_LEVEL_LINKING=OFF \ - -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \ - -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \ - -DANDROID_STL=c++_shared \ - -DANDROID_ABI=${ANDROID_ABI} \ - -DANDROID_NDK=${ANDROID_NDK} \ - -DTHIRDPARTY=ON \ - -DCOMPILE_EXAMPLES=OFF \ - -DCMAKE_FIND_ROOT_PATH="${PWD}/install" +# build_android: +# runs-on: ubuntu-18.04 +# steps: +# - name: Install Java +# run: | +# sudo apt-get update -qq +# sudo apt-get install -y default-jdk gradle +# - uses: actions/checkout@v2 +# - name: Setup locale for ROS 2 +# run: | +# sudo locale-gen en_US en_US.UTF-8 +# sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 +# export LANG=en_US.UTF-8 +# - name: Setup sources for ROS 2 +# run: | +# sudo apt-get update && sudo apt-get install -y curl gnupg2 lsb-release +# curl -sL https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add - +# sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list' +# - name: Install ROS 2 dependencies +# run: | +# sudo apt-get update && sudo apt-get install -y python3-colcon-common-extensions python3-vcstool python3-lark-parser python3-dev +# - name: Install colcon extensions for Gradle +# run: | +# sudo pip3 install git+git://github.com/colcon/colcon-gradle.git +# sudo pip3 install git+git://github.com/colcon/colcon-ros-gradle.git +# - name: Install Android NDK +# run: | +# curl -LO https://dl.google.com/android/repository/android-ndk-r21d-linux-x86_64.zip +# unzip android-ndk-r21d-linux-x86_64.zip +# - name: Setup workspace with VCS repo file +# run: | +# mkdir -p ros2_java_ws/src +# cd ros2_java_ws +# curl -sL file://${{ github.workspace }}/ros2_java_android.repos | vcs import src +# # Use checked out version of ros2_java +# rm -rf src/ros2_java/ros2_java +# ln --symbolic ${{ github.workspace }} src/ros2_java +# - name: Build ros2_java for Android +# run: | +# export PYTHON3_EXEC="$( which python3 )" +# export PYTHON3_LIBRARY="$( ${PYTHON3_EXEC} -c 'import os.path; from distutils import sysconfig; print(os.path.realpath(os.path.join(sysconfig.get_config_var("LIBPL"), sysconfig.get_config_var("LDLIBRARY"))))' )" +# export PYTHON3_INCLUDE_DIR="$( ${PYTHON3_EXEC} -c 'from distutils import sysconfig; print(sysconfig.get_config_var("INCLUDEPY"))' )" +# export ANDROID_ABI=armeabi-v7a +# export ANDROID_NATIVE_API_LEVEL=android-21 +# export ANDROID_TOOLCHAIN_NAME=arm-linux-androideabi-clang +# export ANDROID_NDK=${PWD}/android-ndk-r21d +# +# cd ros2_java_ws +# colcon build \ +# --packages-ignore cyclonedds rcl_logging_log4cxx rosidl_generator_py \ +# --packages-up-to rcljava \ +# --cmake-args \ +# -DPYTHON_EXECUTABLE=${PYTHON3_EXEC} \ +# -DPYTHON_LIBRARY=${PYTHON3_LIBRARY} \ +# -DPYTHON_INCLUDE_DIR=${PYTHON3_INCLUDE_DIR} \ +# -DCMAKE_TOOLCHAIN_FILE=${ANDROID_NDK}/build/cmake/android.toolchain.cmake \ +# -DANDROID_FUNCTION_LEVEL_LINKING=OFF \ +# -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \ +# -DANDROID_TOOLCHAIN_NAME=${ANDROID_TOOLCHAIN_NAME} \ +# -DANDROID_STL=c++_shared \ +# -DANDROID_ABI=${ANDROID_ABI} \ +# -DANDROID_NDK=${ANDROID_NDK} \ +# -DTHIRDPARTY=ON \ +# -DCOMPILE_EXAMPLES=OFF \ +# -DCMAKE_FIND_ROOT_PATH="${PWD}/install"