hc
2023-05-26 a23f51ed7a39e452c1037343a84d7db1ca2c5bd7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#!/bin/bash
set -euxo pipefail
 
# ROS_DISTRO will be overrided when docker image build
ROS_DISTRO=
 
export LD_LIBRARY_PATH=/buildroot/host/lib/
export SYSROOT=/buildroot/host/aarch64-buildroot-linux-gnu/sysroot/
export CC=/buildroot/host/bin/aarch64-buildroot-linux-gnu-gcc
export CXX=/buildroot/host/bin/aarch64-buildroot-linux-gnu-g++
export CROSS_COMPILE=/buildroot/host/bin/aarch64-buildroot-linux-gnu-
export TARGET_ARCH=aarch64
# Consist with buildroot target, not flag:m.
# flag:m(cpython-38m...) is enabled by --with-pymalloc
export PYTHON_SOABI=cpython-38-aarch64-linux-gnu
export ROS2_INSTALL_PATH=/buildroot/target/opt/ros/
export TARGET_TRIPLE=/buildroot/host/bin/aarch64-buildroot-linux-gnu
export ARCH=aarch64
 
cleanup() {
  git -C src/ros2/mimick_vendor/ checkout .
 
  if [ -e src/ros2/pybind11_vendor/CMakeLists.txt ]; then
     git -C src/ros2/pybind11_vendor/ checkout .
  fi
 
  if [ -e src/ros2/python_cmake_module/ ]; then
     git -C src/ros2/python_cmake_module/ checkout .
  fi
 
  echo "Strip Elf Object files"
 
  # *.a : static library that must including symbols
  KNOWN_NO_BINARY="xml|py|dsv|sh|ps1|bash|zsh|cmake|msg|idl|in|action|srv|yaml|gz|em|cpp|h|hpp|md|cc|c|bat|a|txt|pyc"
  find ${ROS2_INSTALL_PATH} -type f -and ! -empty \
    -and -regextype posix-extended ! -regex ".*\.(${KNOWN_NO_BINARY})" \
    -exec grep -IL '' "{}" \; | xargs ${CROSS_COMPILE}strip
 
  echo "build ros quit & cleanup source changes"
}
 
trap 'cleanup' EXIT
 
prepare_source() {
  #FIXME: camke set wrong mimick_vendor ARCH when building, in file:
  #       CMakeFiles/3.16.3/CMakeSystem.cmake. This probably because
  #       qemu can run binary for aarch target directly inside Docker image, which broken cmake configuration.
  # Workaround by set SYSTEM_NAME and SYSTEM_PROCESSER manually
  sed -i '/^.*ExternalProject.*$/i \ \ list(APPEND cmake_configure_args "-DCMAKE_SYSTEM_NAME=${CMAKE_SYSTEM_NAME}") \n\ \ list(APPEND cmake_configure_args "-DCMAKE_SYSTEM_PROCESSOR=${CMAKE_SYSTEM_PROCESSOR}")' \
    src/ros2/mimick_vendor/CMakeLists.txt
 
  # When building galactic's rclpy package:
  #   ./ros/share/cmake/pybind11/pybind11Config.cmake:
  #     -> ./ros/share/cmake/pybind11/pybind11Tools.cmake:   find_package(PythonLibsNew
  #       -> ./ros/share/cmake/pybind11/FindPythonLibsNew.cmake
  # it read host's PYTHON_INCLUDE_DIRS, for example:
  #  $ grep isystem /opt/ros/
  #    .... -isystem /data/ros/install/include ...
  # A hack as below can workaround and continue building:
  #  - colcon build --packages-up-to pybind11, and then,
  #  - Change PythonLibsNew to PythonLibs before building other packages
  # but it can not set PYTHON_MODULE_EXTENSION correctly.
  #
  # To cross compile for aarch64 target, update to new version of pybind11
  # see: https://github.com/pybind/pybind11/issues/2139, bug reported
  #      https://github.com/pybind/pybind11/pull/2370, which fixed by introducing "FindPython Mode"
  if [ -e src/ros2/pybind11_vendor/CMakeLists.txt ]; then
    sed -i 's|ExternalProject_Add(pybind11.*$|ExternalProject_Add(pybind11-2.7.1|' \
      src/ros2/pybind11_vendor/CMakeLists.txt
    sed -i 's|archive/v.*$|archive/v2.7.1.tar.gz|' \
      src/ros2/pybind11_vendor/CMakeLists.txt
    sed -i 's|URL_MD5.*$|URL_MD5 b87860218c143728f8e6efa6cba7e1ed|' \
      src/ros2/pybind11_vendor/CMakeLists.txt
  fi
 
  # Use new FindPython Mode, so pybind11 will include pybind11Tools.cmake instead of
  # pybind11Tools.cmake which finds PythonLibsNew and overrides PYTHON_* from host.
  if [ -e src/ros2/python_cmake_module/cmake/Modules/FindPythonExtra.cmake ]; then
    sed -i 's|^find_package(PythonInterp.*$|find_package(Python COMPONENTS Interpreter Development)|' \
      src/ros2/python_cmake_module/cmake/Modules/FindPythonExtra.cmake
    sed -i '/^.*find_package_handle_standard_args.*$/i set(PYTHON_MODULE_EXTENSION "${PythonExtra_EXTENSION_SUFFIX}${PythonExtra_EXTENSION_EXTENSION}" CACHE INTERNAL "")' \
      src/ros2/python_cmake_module/cmake/Modules/FindPythonExtra.cmake
  fi
}
 
prepare_source
 
mkdir -p /buildroot/build/ros /buildroot/target/opt/ros
# cmake's find_package only search sysroot path if CMAKE_SYSROOT has defined
# setting COLCON_CURRENT_PREFIX instead?
pushd /buildroot/host/aarch64-buildroot-linux-gnu/sysroot/
rm -rf opt
ln -sf ../../../target/opt/ros/ opt
popd
 
#FIXME: link buildroot binfmt just because CROSSCOMPILING_EMULATOR don't work
#       when building foonathan_memory_vendor, and installing qemu-user-static/qemu-user-binfmt
#       packages require root privilege. The CMAKE_CROSSCOMPILING_EMULATOR doesn't work too.
#       "-DCMAKE_CROSSCOMPILING_EMULATOR=/usr/bin/qemu-aarch64-static;-L;/buildroot/target/"
mkdir -p /etc/qemu-binfmt
ln -sf /buildroot/target/ /etc/qemu-binfmt/aarch64
 
# install mixin which setup building evinronments
colcon mixin remove default || true
colcon mixin add default file:///root/index.yaml
colcon mixin update default
 
# HINTS:
#  - Use --merge-install to avoid some find_package/find_path/find_library fails
 
LDFLAGS="-L/buildroot/host/lib -Wl,-rpath,/buildroot/host/lib" \
  CFLAGS="-O2 -I/buildroot/host/include/" \
  colcon build \
  --mixin aarch64-linux \
  --merge-install \
  --build-base /buildroot/build/ros/ \
  --install-base /buildroot/target/opt/ros \
  --cmake-force-configure \
# --packages-select  rclpy