在 docker 容器中构建 ROS2 工作区——找不到 ament_cmake
Build ROS2 workspace in docker container -- cannot find ament_cmake
我有一个这样的 ROS2 工作区项目:
├── build-in-docker
├── docker
│ ├── build
│ ├── Dockerfile
│ └── env
└── src
docker/env
有环境变量:
#!/bin/bash
NOC='3[0m'
GRN='3[0;32m'
YLW='3[0;33m'
image_name="docker-build-ros2"
container_name="ros2-ws"
target_path="/ros2-ws"
和docker/Dockerfile
有内容:
# syntax=docker/dockerfile:experimental
# prepare the docker -----------------
FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
# By default, ubuntu docker images include code to remove downloaded packages.
# Use the invocation from examples to avoid this and make the apt cache effective.
RUN rm -f /etc/apt/apt.conf.d/docker-clean \
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \
> /etc/apt/apt.conf.d/keep-cache
ENV ROS_PYTHON_VERSION 3
RUN apt-get update && apt-get install -y locales
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
# run export DOCKER_BUILDKIT=1 to enable BuildKit
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get --no-install-recommends install -y \
autoconf bash-completion build-essential cmake curl \
dirmngr gcc git gnupg2 g++ libtool lsb-release \
pkg-config python3-pip libccd-dev \
libflann-dev libpcl-dev libyaml-cpp-dev \
&& pip3 install cython \
&& rm -rf /var/lib/apt/lists/*
RUN export LANG=en_US.UTF-8
RUN curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add -
RUN 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'
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get --no-install-recommends install -y \
ros-foxy-desktop \
python3-argcomplete \
python3-colcon-common-extensions \
python3-colcon-mixin \
python3-rosdep \
python3-vcstool \
&& rm -rf /var/lib/apt/lists/*
RUN rosdep init || true \
&& rosdep update
RUN echo "source /opt/ros/foxy/setup.bash" >> /etc/bash.bashrc
RUN echo "source /opt/ros/foxy/local_setup.bash" >> /etc/bash.bashrc
然后,我将使用build-in-docker
脚本构建ROS2工作区,build-in-docker
有内容:
#!/bin/bash
set -eu -o pipefail
script_dir="$(dirname "[=15=]")"
pushd "$script_dir" &>/dev/null
source "$script_dir/docker/env"
# stop the container if it is running ------------------------
if [[ $(docker ps --filter "name=^/${container_name}$" --format '{{.Names}}') == "${container_name}" &&
"$(docker container inspect -f '{{.State.Running}}' ${container_name})" == "true" ]]; then
echo -e "${YLW}Stop container \"${container_name}\"${NOC} ..."
docker stop ${container_name}
fi
# remove the container if it exists but not running ------------------------
if [[ $(docker ps --filter "name=^/${container_name}$" --format '{{.Names}}') == "${container_name}" ]]; then
echo -e "${YLW}Remove container \"${container_name}\"${NOC} ..."
docker rm ${container_name} &>/dev/null
fi
# build an image from Dockerfile ------------------------
echo -e "${GRN}Build the image \"${image_name}\"${NOC} ..."
DOCKER_BUILDKIT=1 docker build \
-t ${image_name} \
-f docker/Dockerfile docker
# create a container and run it ------------------------
echo -e "${GRN}Run container \"${container_name}\" from image \"${image_name}\"${NOC} ..."
docker run -d -it --rm \
--name ${container_name} \
--mount type=bind,source="$(pwd)",target=${target_path} \
${image_name}
# build the project in the container ------------------------
# ${target_path} ${build_dir}: arguments passed into ./docker/build
echo -e "${GRN}Build the project${NOC} ..."
docker exec ${container_name} ${target_path}/docker/build \
${target_path}
# finish
echo -e "${GRN}Project is build successfully.${NOC}"
popd &>/dev/null
调用 docker/build
脚本:
#!/bin/bash
set -eu -o pipefail
# project root directory, passed from ../build-in-docker
cd ""
/bin/bash -c "source /opt/ros/foxy/setup.bash"
colcon build
但是,它给我错误:
Stop container "ros2-ws" ...
ros2-ws
Build the image "docker-build-ros2" ...
[+] Building 0.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 38B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:experimental 0.1s
=> CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:600e5c 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.1s
=> [stage-0 1/12] FROM docker.io/library/ubuntu:20.04@sha256:626ffe58f6e7566e0 0.0s
=> CACHED [stage-0 2/12] RUN rm -f /etc/apt/apt.conf.d/docker-clean && ech 0.0s
=> CACHED [stage-0 3/12] RUN apt-get update && apt-get install -y locales 0.0s
=> CACHED [stage-0 4/12] RUN locale-gen en_US.UTF-8 0.0s
=> CACHED [stage-0 5/12] RUN --mount=type=cache,target=/var/cache/apt,sharing= 0.0s
=> CACHED [stage-0 6/12] RUN export LANG=en_US.UTF-8 0.0s
=> CACHED [stage-0 7/12] RUN curl -s https://raw.githubusercontent.com/ros/ros 0.0s
=> CACHED [stage-0 8/12] RUN sh -c 'echo "deb [arch=$(dpkg --print-architectur 0.0s
=> CACHED [stage-0 9/12] RUN --mount=type=cache,target=/var/cache/apt,sharing= 0.0s
=> CACHED [stage-0 10/12] RUN rosdep init || true && rosdep update 0.0s
=> CACHED [stage-0 11/12] RUN echo "source /opt/ros/foxy/setup.bash" >> /etc/ba 0.0s
=> CACHED [stage-0 12/12] RUN echo "source /opt/ros/foxy/local_setup.bash" >> / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:9af6dcfcf4fa94cec435a91fd48218c6b83c730aada6de85cc86 0.0s
=> => naming to docker.io/library/docker-build-ros2 0.0s
Run container "ros2-ws" from image "docker-build-ros2" ...
ff1545051e411035142315215ab385d74627d7de65e79a22ec12b0c59f656790
Build the project ...
Starting >>> agv_interfaces
--- stderr: agv_interfaces
CMake Error at CMakeLists.txt:19 (find_package):
By not providing "Findament_cmake.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"ament_cmake", but CMake did not find one.
Could not find a package configuration file provided by "ament_cmake" with
any of the following names:
ament_cmakeConfig.cmake
ament_cmake-config.cmake
Add the installation prefix of "ament_cmake" to CMAKE_PREFIX_PATH or set
"ament_cmake_DIR" to a directory containing one of the above files. If
"ament_cmake" provides a separate development package or SDK, be sure it
has been installed.
---
Failed <<< agv_interfaces [0.07s, exited with code 1]
Summary: 0 packages finished [0.26s]
1 package failed: agv_interfaces
1 package had stderr output: agv_interfaces
1 package not processed
但是,如果我使用docker attach
命令手动进入容器,并手动进入目录,然后使用colcon build
构建工作区,则构建成功。在此之后,如果我再次运行 ./build-in-docker
native,则可以成功构建worspace。
我的问题是,我做错了什么设置导致我无法从第一个 运行ning ./build-in-docker
命令构建工作区?
在您正在执行的构建脚本中:
/bin/bash -c "source /opt/ros/foxy/setup.bash"
将/bin/bash
放在你的命令前面只是打开一个新的命令行,执行命令,然后关闭命令行。
因此,无论您在该命令中输入什么,它都会立即消失。
因此,只需将其更改为:
source /opt/ros/foxy/setup.bash
正如另一个答案中指出的那样,您需要改用 source /opt/ros/foxy/setup.bash
。这产生的新错误是由于 build-in-docker
文件中的行 set -eu -o pipefail
。 -u
标志会将每个未设置的变量视为错误。您可以删除标志或将 AMENT_TRACE_SETUP_FILES
设置为某个值。
我有一个这样的 ROS2 工作区项目:
├── build-in-docker
├── docker
│ ├── build
│ ├── Dockerfile
│ └── env
└── src
docker/env
有环境变量:
#!/bin/bash
NOC='3[0m'
GRN='3[0;32m'
YLW='3[0;33m'
image_name="docker-build-ros2"
container_name="ros2-ws"
target_path="/ros2-ws"
和docker/Dockerfile
有内容:
# syntax=docker/dockerfile:experimental
# prepare the docker -----------------
FROM ubuntu:20.04
ARG DEBIAN_FRONTEND=noninteractive
# By default, ubuntu docker images include code to remove downloaded packages.
# Use the invocation from examples to avoid this and make the apt cache effective.
RUN rm -f /etc/apt/apt.conf.d/docker-clean \
&& echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' \
> /etc/apt/apt.conf.d/keep-cache
ENV ROS_PYTHON_VERSION 3
RUN apt-get update && apt-get install -y locales
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
# run export DOCKER_BUILDKIT=1 to enable BuildKit
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get --no-install-recommends install -y \
autoconf bash-completion build-essential cmake curl \
dirmngr gcc git gnupg2 g++ libtool lsb-release \
pkg-config python3-pip libccd-dev \
libflann-dev libpcl-dev libyaml-cpp-dev \
&& pip3 install cython \
&& rm -rf /var/lib/apt/lists/*
RUN export LANG=en_US.UTF-8
RUN curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | apt-key add -
RUN 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'
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
apt-get update && apt-get --no-install-recommends install -y \
ros-foxy-desktop \
python3-argcomplete \
python3-colcon-common-extensions \
python3-colcon-mixin \
python3-rosdep \
python3-vcstool \
&& rm -rf /var/lib/apt/lists/*
RUN rosdep init || true \
&& rosdep update
RUN echo "source /opt/ros/foxy/setup.bash" >> /etc/bash.bashrc
RUN echo "source /opt/ros/foxy/local_setup.bash" >> /etc/bash.bashrc
然后,我将使用build-in-docker
脚本构建ROS2工作区,build-in-docker
有内容:
#!/bin/bash
set -eu -o pipefail
script_dir="$(dirname "[=15=]")"
pushd "$script_dir" &>/dev/null
source "$script_dir/docker/env"
# stop the container if it is running ------------------------
if [[ $(docker ps --filter "name=^/${container_name}$" --format '{{.Names}}') == "${container_name}" &&
"$(docker container inspect -f '{{.State.Running}}' ${container_name})" == "true" ]]; then
echo -e "${YLW}Stop container \"${container_name}\"${NOC} ..."
docker stop ${container_name}
fi
# remove the container if it exists but not running ------------------------
if [[ $(docker ps --filter "name=^/${container_name}$" --format '{{.Names}}') == "${container_name}" ]]; then
echo -e "${YLW}Remove container \"${container_name}\"${NOC} ..."
docker rm ${container_name} &>/dev/null
fi
# build an image from Dockerfile ------------------------
echo -e "${GRN}Build the image \"${image_name}\"${NOC} ..."
DOCKER_BUILDKIT=1 docker build \
-t ${image_name} \
-f docker/Dockerfile docker
# create a container and run it ------------------------
echo -e "${GRN}Run container \"${container_name}\" from image \"${image_name}\"${NOC} ..."
docker run -d -it --rm \
--name ${container_name} \
--mount type=bind,source="$(pwd)",target=${target_path} \
${image_name}
# build the project in the container ------------------------
# ${target_path} ${build_dir}: arguments passed into ./docker/build
echo -e "${GRN}Build the project${NOC} ..."
docker exec ${container_name} ${target_path}/docker/build \
${target_path}
# finish
echo -e "${GRN}Project is build successfully.${NOC}"
popd &>/dev/null
调用 docker/build
脚本:
#!/bin/bash
set -eu -o pipefail
# project root directory, passed from ../build-in-docker
cd ""
/bin/bash -c "source /opt/ros/foxy/setup.bash"
colcon build
但是,它给我错误:
Stop container "ros2-ws" ...
ros2-ws
Build the image "docker-build-ros2" ...
[+] Building 0.7s (18/18) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 38B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> resolve image config for docker.io/docker/dockerfile:experimental 0.1s
=> CACHED docker-image://docker.io/docker/dockerfile:experimental@sha256:600e5c 0.0s
=> [internal] load metadata for docker.io/library/ubuntu:20.04 0.1s
=> [stage-0 1/12] FROM docker.io/library/ubuntu:20.04@sha256:626ffe58f6e7566e0 0.0s
=> CACHED [stage-0 2/12] RUN rm -f /etc/apt/apt.conf.d/docker-clean && ech 0.0s
=> CACHED [stage-0 3/12] RUN apt-get update && apt-get install -y locales 0.0s
=> CACHED [stage-0 4/12] RUN locale-gen en_US.UTF-8 0.0s
=> CACHED [stage-0 5/12] RUN --mount=type=cache,target=/var/cache/apt,sharing= 0.0s
=> CACHED [stage-0 6/12] RUN export LANG=en_US.UTF-8 0.0s
=> CACHED [stage-0 7/12] RUN curl -s https://raw.githubusercontent.com/ros/ros 0.0s
=> CACHED [stage-0 8/12] RUN sh -c 'echo "deb [arch=$(dpkg --print-architectur 0.0s
=> CACHED [stage-0 9/12] RUN --mount=type=cache,target=/var/cache/apt,sharing= 0.0s
=> CACHED [stage-0 10/12] RUN rosdep init || true && rosdep update 0.0s
=> CACHED [stage-0 11/12] RUN echo "source /opt/ros/foxy/setup.bash" >> /etc/ba 0.0s
=> CACHED [stage-0 12/12] RUN echo "source /opt/ros/foxy/local_setup.bash" >> / 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:9af6dcfcf4fa94cec435a91fd48218c6b83c730aada6de85cc86 0.0s
=> => naming to docker.io/library/docker-build-ros2 0.0s
Run container "ros2-ws" from image "docker-build-ros2" ...
ff1545051e411035142315215ab385d74627d7de65e79a22ec12b0c59f656790
Build the project ...
Starting >>> agv_interfaces
--- stderr: agv_interfaces
CMake Error at CMakeLists.txt:19 (find_package):
By not providing "Findament_cmake.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"ament_cmake", but CMake did not find one.
Could not find a package configuration file provided by "ament_cmake" with
any of the following names:
ament_cmakeConfig.cmake
ament_cmake-config.cmake
Add the installation prefix of "ament_cmake" to CMAKE_PREFIX_PATH or set
"ament_cmake_DIR" to a directory containing one of the above files. If
"ament_cmake" provides a separate development package or SDK, be sure it
has been installed.
---
Failed <<< agv_interfaces [0.07s, exited with code 1]
Summary: 0 packages finished [0.26s]
1 package failed: agv_interfaces
1 package had stderr output: agv_interfaces
1 package not processed
但是,如果我使用docker attach
命令手动进入容器,并手动进入目录,然后使用colcon build
构建工作区,则构建成功。在此之后,如果我再次运行 ./build-in-docker
native,则可以成功构建worspace。
我的问题是,我做错了什么设置导致我无法从第一个 运行ning ./build-in-docker
命令构建工作区?
在您正在执行的构建脚本中:
/bin/bash -c "source /opt/ros/foxy/setup.bash"
将/bin/bash
放在你的命令前面只是打开一个新的命令行,执行命令,然后关闭命令行。
因此,无论您在该命令中输入什么,它都会立即消失。
因此,只需将其更改为:
source /opt/ros/foxy/setup.bash
正如另一个答案中指出的那样,您需要改用 source /opt/ros/foxy/setup.bash
。这产生的新错误是由于 build-in-docker
文件中的行 set -eu -o pipefail
。 -u
标志会将每个未设置的变量视为错误。您可以删除标志或将 AMENT_TRACE_SETUP_FILES
设置为某个值。