mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-04-14 10:07:39 +08:00
build(packaging): add PX4 SITL .deb packages
Add cmake/cpack infrastructure for building .deb packages from px4_sitl_sih and px4_sitl_default targets. Includes install rules, package scripts, Gazebo wrapper, and CI workflow. Signed-off-by: Ramon Roche <mrpollo@gmail.com>
This commit is contained in:
parent
ebe0b727d8
commit
1079c57fd0
1
.dockerignore
Normal file
1
.dockerignore
Normal file
@ -0,0 +1 @@
|
|||||||
|
build/
|
||||||
115
.github/actions/build-deb/action.yml
vendored
Normal file
115
.github/actions/build-deb/action.yml
vendored
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
name: Build PX4 .deb Package
|
||||||
|
description: Build PX4 SITL, run cpack, validate the .deb, and upload artifact
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
target:
|
||||||
|
description: 'Build target: default or sih'
|
||||||
|
required: true
|
||||||
|
artifact-name:
|
||||||
|
description: Name for the uploaded artifact
|
||||||
|
required: true
|
||||||
|
ccache-key-prefix:
|
||||||
|
description: Prefix for ccache cache keys
|
||||||
|
default: deb-ccache
|
||||||
|
ccache-max-size:
|
||||||
|
description: Maximum ccache size
|
||||||
|
default: 400M
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Restore ccache
|
||||||
|
id: ccache-restore
|
||||||
|
uses: actions/cache/restore@v4
|
||||||
|
with:
|
||||||
|
path: ~/.ccache
|
||||||
|
key: ${{ inputs.ccache-key-prefix }}-${{ github.ref_name }}-${{ github.sha }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ inputs.ccache-key-prefix }}-${{ github.ref_name }}-
|
||||||
|
${{ inputs.ccache-key-prefix }}-${{ github.base_ref || 'main' }}-
|
||||||
|
${{ inputs.ccache-key-prefix }}-
|
||||||
|
|
||||||
|
- name: Configure ccache
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ccache
|
||||||
|
echo "base_dir = ${GITHUB_WORKSPACE}" > ~/.ccache/ccache.conf
|
||||||
|
echo "compression = true" >> ~/.ccache/ccache.conf
|
||||||
|
echo "compression_level = 6" >> ~/.ccache/ccache.conf
|
||||||
|
echo "max_size = ${{ inputs.ccache-max-size }}" >> ~/.ccache/ccache.conf
|
||||||
|
echo "hash_dir = false" >> ~/.ccache/ccache.conf
|
||||||
|
echo "compiler_check = content" >> ~/.ccache/ccache.conf
|
||||||
|
ccache -s
|
||||||
|
ccache -z
|
||||||
|
|
||||||
|
- name: Build PX4 SITL
|
||||||
|
shell: bash
|
||||||
|
run: make px4_sitl_${{ inputs.target }}
|
||||||
|
|
||||||
|
- name: ccache stats
|
||||||
|
if: always()
|
||||||
|
shell: bash
|
||||||
|
run: ccache -s
|
||||||
|
|
||||||
|
- name: Save ccache
|
||||||
|
uses: actions/cache/save@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
path: ~/.ccache
|
||||||
|
key: ${{ inputs.ccache-key-prefix }}-${{ github.ref_name }}-${{ github.sha }}
|
||||||
|
|
||||||
|
- name: Build .deb package
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd build/px4_sitl_${{ inputs.target }}
|
||||||
|
cpack -G DEB
|
||||||
|
|
||||||
|
- name: Print package info and contents
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd build/px4_sitl_${{ inputs.target }}
|
||||||
|
echo "--- Package info ---"
|
||||||
|
dpkg-deb -I *.deb
|
||||||
|
echo "--- Package contents ---"
|
||||||
|
dpkg-deb -c *.deb
|
||||||
|
|
||||||
|
- name: Validate sih package
|
||||||
|
if: inputs.target == 'sih'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd build/px4_sitl_sih
|
||||||
|
echo "--- Verify NO Gazebo resources ---"
|
||||||
|
! dpkg-deb -c px4_*.deb | grep share/gz > /dev/null && echo "PASS: no Gazebo" || { echo "FAIL: Gazebo found"; exit 1; }
|
||||||
|
echo "--- Install test ---"
|
||||||
|
dpkg -i px4_*.deb
|
||||||
|
test -x /opt/px4/bin/px4 || { echo "FAIL: px4 binary not found"; exit 1; }
|
||||||
|
test -L /usr/bin/px4 || { echo "FAIL: symlink not created"; exit 1; }
|
||||||
|
test ! -d /opt/px4/share/gz || { echo "FAIL: Gazebo dir should not exist"; exit 1; }
|
||||||
|
echo "--- Smoke test ---"
|
||||||
|
/opt/px4/bin/px4 -h
|
||||||
|
echo "PASS: sih package validation successful"
|
||||||
|
|
||||||
|
- name: Validate gazebo package
|
||||||
|
if: inputs.target == 'default'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd build/px4_sitl_default
|
||||||
|
echo "--- Verify Gazebo resources in package ---"
|
||||||
|
dpkg-deb -c px4-gazebo_*.deb | grep share/gz/models > /dev/null || { echo "FAIL: models missing"; exit 1; }
|
||||||
|
dpkg-deb -c px4-gazebo_*.deb | grep share/gz/worlds > /dev/null || { echo "FAIL: worlds missing"; exit 1; }
|
||||||
|
echo "--- Install test ---"
|
||||||
|
dpkg -i px4-gazebo_*.deb
|
||||||
|
test -x /opt/px4-gazebo/bin/px4 || { echo "FAIL: px4 binary not found"; exit 1; }
|
||||||
|
test -x /opt/px4-gazebo/bin/px4-gazebo || { echo "FAIL: wrapper not found"; exit 1; }
|
||||||
|
test -L /usr/bin/px4-gazebo || { echo "FAIL: symlink not created"; exit 1; }
|
||||||
|
test -d /opt/px4-gazebo/share/gz/models || { echo "FAIL: Gazebo models not installed"; exit 1; }
|
||||||
|
echo "--- Smoke test ---"
|
||||||
|
/opt/px4-gazebo/bin/px4 -h
|
||||||
|
echo "PASS: gazebo package validation successful"
|
||||||
|
|
||||||
|
- name: Upload .deb artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ inputs.artifact-name }}
|
||||||
|
path: build/px4_sitl_${{ inputs.target }}/*.deb
|
||||||
|
if-no-files-found: error
|
||||||
252
.github/workflows/build_deb_package.yml
vendored
Normal file
252
.github/workflows/build_deb_package.yml
vendored
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
name: SITL Packages and Containers
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags: ['v*']
|
||||||
|
pull_request:
|
||||||
|
paths:
|
||||||
|
- 'cmake/package.cmake'
|
||||||
|
- 'platforms/posix/CMakeLists.txt'
|
||||||
|
- 'Tools/packaging/**'
|
||||||
|
- 'boards/px4/sitl/sih.px4board'
|
||||||
|
- '.github/workflows/build_deb_package.yml'
|
||||||
|
- '.github/actions/build-deb/**'
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
deploy_containers:
|
||||||
|
description: 'Push container images to registry'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
RUNS_IN_DOCKER: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Setup: extract version and determine whether to push containers
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
setup:
|
||||||
|
name: Setup
|
||||||
|
runs-on: [runs-on,"runner=1cpu-linux-x64","image=ubuntu24-full-x64","run-id=${{ github.run_id }}",extras=s3-cache,spot=false]
|
||||||
|
outputs:
|
||||||
|
px4_version: ${{ steps.px4_version.outputs.px4_version }}
|
||||||
|
should_push: ${{ steps.push_check.outputs.should_push }}
|
||||||
|
steps:
|
||||||
|
- uses: runs-on/action@v2
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-tags: true
|
||||||
|
submodules: false
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Set PX4 version
|
||||||
|
id: px4_version
|
||||||
|
run: echo "px4_version=$(git describe --tags --match 'v[0-9]*')" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Check if we should push containers
|
||||||
|
id: push_check
|
||||||
|
run: |
|
||||||
|
if [[ "${{ startsWith(github.ref, 'refs/tags/') }}" == "true" ]] || \
|
||||||
|
[[ "${{ github.event_name }}" == "workflow_dispatch" && "${{ github.event.inputs.deploy_containers }}" == "true" ]]; then
|
||||||
|
echo "should_push=true" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "should_push=false" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Build .deb packages (all distros, arches, targets)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
build-deb:
|
||||||
|
name: "Build .deb (${{ matrix.target }}/${{ matrix.codename }}/${{ matrix.arch }})"
|
||||||
|
needs: setup
|
||||||
|
runs-on: [runs-on,"runner=4cpu-linux-${{ matrix.runner }}","image=ubuntu24-full-${{ matrix.runner }}","run-id=${{ github.run_id }}",extras=s3-cache,spot=false]
|
||||||
|
container:
|
||||||
|
image: ${{ matrix.container }}
|
||||||
|
volumes:
|
||||||
|
- /github/workspace:/github/workspace
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
# Gazebo builds
|
||||||
|
- { codename: noble, arch: amd64, runner: x64, container: "ubuntu:24.04", target: default, setup_flags: "" }
|
||||||
|
- { codename: noble, arch: arm64, runner: arm64, container: "ubuntu:24.04", target: default, setup_flags: "" }
|
||||||
|
- { codename: jammy, arch: amd64, runner: x64, container: "ubuntu:22.04", target: default, setup_flags: "" }
|
||||||
|
- { codename: jammy, arch: arm64, runner: arm64, container: "ubuntu:22.04", target: default, setup_flags: "" }
|
||||||
|
# SIH builds
|
||||||
|
- { codename: noble, arch: amd64, runner: x64, container: "ubuntu:24.04", target: sih, setup_flags: "--no-sim-tools" }
|
||||||
|
- { codename: noble, arch: arm64, runner: arm64, container: "ubuntu:24.04", target: sih, setup_flags: "--no-sim-tools" }
|
||||||
|
- { codename: jammy, arch: amd64, runner: x64, container: "ubuntu:22.04", target: sih, setup_flags: "--no-sim-tools" }
|
||||||
|
- { codename: jammy, arch: arm64, runner: arm64, container: "ubuntu:22.04", target: sih, setup_flags: "--no-sim-tools" }
|
||||||
|
steps:
|
||||||
|
- uses: runs-on/action@v2
|
||||||
|
|
||||||
|
- name: Fix git in container
|
||||||
|
run: |
|
||||||
|
apt-get update && apt-get install -y git
|
||||||
|
git config --global --add safe.directory $(realpath .)
|
||||||
|
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
fetch-tags: true
|
||||||
|
|
||||||
|
- name: Cache apt packages
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: /var/cache/apt/archives
|
||||||
|
key: apt-${{ matrix.target }}-${{ matrix.codename }}-${{ matrix.arch }}-${{ hashFiles('Tools/setup/ubuntu.sh') }}
|
||||||
|
restore-keys: apt-${{ matrix.target }}-${{ matrix.codename }}-${{ matrix.arch }}-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: ./Tools/setup/ubuntu.sh --no-nuttx ${{ matrix.setup_flags }}
|
||||||
|
|
||||||
|
- name: Build and package .deb
|
||||||
|
uses: ./.github/actions/build-deb
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.target }}
|
||||||
|
artifact-name: px4-sitl-debs-${{ matrix.target }}-${{ matrix.codename }}-${{ matrix.arch }}
|
||||||
|
ccache-key-prefix: deb-ccache-${{ matrix.target }}-${{ matrix.codename }}-${{ matrix.arch }}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Build Docker images from Noble .debs
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
build-docker:
|
||||||
|
name: "Build Image (${{ matrix.image }}/${{ matrix.arch }})"
|
||||||
|
needs: [setup, build-deb]
|
||||||
|
runs-on: [runs-on,"runner=4cpu-linux-${{ matrix.runner }}","image=ubuntu24-full-${{ matrix.runner }}","run-id=${{ github.run_id }}",extras=s3-cache,spot=false]
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- { image: sih, target: sih, arch: amd64, runner: x64, platform: "linux/amd64", dockerfile: Dockerfile.sih }
|
||||||
|
- { image: sih, target: sih, arch: arm64, runner: arm64, platform: "linux/arm64", dockerfile: Dockerfile.sih }
|
||||||
|
- { image: gazebo, target: default, arch: amd64, runner: x64, platform: "linux/amd64", dockerfile: Dockerfile.gazebo }
|
||||||
|
- { image: gazebo, target: default, arch: arm64, runner: arm64, platform: "linux/arm64", dockerfile: Dockerfile.gazebo }
|
||||||
|
steps:
|
||||||
|
- uses: runs-on/action@v2
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
submodules: false
|
||||||
|
fetch-depth: 1
|
||||||
|
|
||||||
|
- name: Download Noble .deb artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: px4-sitl-debs-${{ matrix.target }}-noble-${{ matrix.arch }}
|
||||||
|
path: docker-context
|
||||||
|
|
||||||
|
- name: Prepare build context
|
||||||
|
run: |
|
||||||
|
cp Tools/packaging/px4-entrypoint.sh docker-context/
|
||||||
|
ls -lh docker-context/
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
if: needs.setup.outputs.should_push == 'true'
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
if: needs.setup.outputs.should_push == 'true'
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
driver: docker-container
|
||||||
|
platforms: ${{ matrix.platform }}
|
||||||
|
|
||||||
|
- name: Build and push container image
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: docker-context
|
||||||
|
file: Tools/packaging/${{ matrix.dockerfile }}
|
||||||
|
tags: |
|
||||||
|
px4io/px4-sitl-${{ matrix.image }}:${{ needs.setup.outputs.px4_version }}-${{ matrix.arch }}
|
||||||
|
ghcr.io/px4/px4-sitl-${{ matrix.image }}:${{ needs.setup.outputs.px4_version }}-${{ matrix.arch }}
|
||||||
|
platforms: ${{ matrix.platform }}
|
||||||
|
load: false
|
||||||
|
push: ${{ needs.setup.outputs.should_push == 'true' }}
|
||||||
|
provenance: false
|
||||||
|
cache-from: type=gha,scope=sitl-${{ matrix.image }}-${{ matrix.arch }}
|
||||||
|
cache-to: type=gha,mode=max,scope=sitl-${{ matrix.image }}-${{ matrix.arch }}
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Deploy: create multi-arch manifests and push to registries
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
deploy:
|
||||||
|
name: "Deploy (${{ matrix.image }})"
|
||||||
|
needs: [setup, build-docker]
|
||||||
|
if: needs.setup.outputs.should_push == 'true'
|
||||||
|
runs-on: [runs-on,"runner=1cpu-linux-x64","image=ubuntu24-full-x64","run-id=${{ github.run_id }}",extras=s3-cache,spot=false]
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
image: [sih, gazebo]
|
||||||
|
steps:
|
||||||
|
- uses: runs-on/action@v2
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Verify per-arch images exist
|
||||||
|
run: |
|
||||||
|
for registry in px4io ghcr.io/px4; do
|
||||||
|
for arch in amd64 arm64; do
|
||||||
|
docker manifest inspect ${registry}/px4-sitl-${{ matrix.image }}:${{ needs.setup.outputs.px4_version }}-${arch} \
|
||||||
|
|| echo "Warning: ${registry}/px4-sitl-${{ matrix.image }}:${{ needs.setup.outputs.px4_version }}-${arch} not found"
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: Create and push multi-arch manifest (Docker Hub)
|
||||||
|
run: |
|
||||||
|
VERSION="${{ needs.setup.outputs.px4_version }}"
|
||||||
|
IMAGE="px4io/px4-sitl-${{ matrix.image }}"
|
||||||
|
|
||||||
|
docker manifest create ${IMAGE}:${VERSION} \
|
||||||
|
--amend ${IMAGE}:${VERSION}-arm64 \
|
||||||
|
--amend ${IMAGE}:${VERSION}-amd64
|
||||||
|
|
||||||
|
docker manifest annotate ${IMAGE}:${VERSION} ${IMAGE}:${VERSION}-arm64 --arch arm64
|
||||||
|
docker manifest annotate ${IMAGE}:${VERSION} ${IMAGE}:${VERSION}-amd64 --arch amd64
|
||||||
|
|
||||||
|
docker manifest push ${IMAGE}:${VERSION}
|
||||||
|
|
||||||
|
- name: Create and push multi-arch manifest (GHCR)
|
||||||
|
run: |
|
||||||
|
VERSION="${{ needs.setup.outputs.px4_version }}"
|
||||||
|
IMAGE="ghcr.io/px4/px4-sitl-${{ matrix.image }}"
|
||||||
|
|
||||||
|
docker manifest create ${IMAGE}:${VERSION} \
|
||||||
|
--amend ${IMAGE}:${VERSION}-arm64 \
|
||||||
|
--amend ${IMAGE}:${VERSION}-amd64
|
||||||
|
|
||||||
|
docker manifest annotate ${IMAGE}:${VERSION} ${IMAGE}:${VERSION}-arm64 --arch arm64
|
||||||
|
docker manifest annotate ${IMAGE}:${VERSION} ${IMAGE}:${VERSION}-amd64 --arch amd64
|
||||||
|
|
||||||
|
docker manifest push ${IMAGE}:${VERSION}
|
||||||
84
Tools/packaging/Dockerfile.gazebo
Normal file
84
Tools/packaging/Dockerfile.gazebo
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
# PX4 SITL Gazebo Harmonic runtime image
|
||||||
|
# Runs PX4 SITL with Gazebo Harmonic. Supports X11 forwarding for GUI.
|
||||||
|
#
|
||||||
|
# Build:
|
||||||
|
# make px4_sitl_default && cd build/px4_sitl_default && cpack -G DEB && cd ../..
|
||||||
|
# docker build -f Tools/packaging/Dockerfile.gazebo -t px4io/px4-sitl-gazebo:v1.17.0 build/px4_sitl_default/
|
||||||
|
#
|
||||||
|
# Run (headless):
|
||||||
|
# docker run --rm -it --network host px4io/px4-sitl-gazebo:v1.17.0
|
||||||
|
#
|
||||||
|
# Run (X11 GUI):
|
||||||
|
# xhost +local:docker
|
||||||
|
# docker run --rm -it --network host \
|
||||||
|
# -e DISPLAY=$DISPLAY -v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||||
|
# --gpus all px4io/px4-sitl-gazebo:v1.17.0
|
||||||
|
|
||||||
|
FROM ubuntu:24.04 AS extract
|
||||||
|
COPY px4-gazebo_*.deb /tmp/
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends binutils \
|
||||||
|
&& dpkg -x /tmp/px4-gazebo_*.deb /staging \
|
||||||
|
&& strip /staging/opt/px4-gazebo/bin/px4 \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
LABEL maintainer="PX4 Development Team"
|
||||||
|
LABEL description="PX4 SITL with Gazebo Harmonic simulation"
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
ENV RUNS_IN_DOCKER=true
|
||||||
|
|
||||||
|
# Install Gazebo Harmonic with buildkit cache mounts for apt
|
||||||
|
# The --mount=type=cache persists /var/cache/apt and /var/lib/apt across builds
|
||||||
|
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||||
|
apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
bc \
|
||||||
|
ca-certificates \
|
||||||
|
gnupg \
|
||||||
|
lsb-release \
|
||||||
|
wget \
|
||||||
|
&& wget -q https://packages.osrfoundation.org/gazebo.gpg \
|
||||||
|
-O /usr/share/keyrings/pkgs-osrf-archive-keyring.gpg \
|
||||||
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/pkgs-osrf-archive-keyring.gpg] http://packages.osrfoundation.org/gazebo/ubuntu-stable $(lsb_release -cs) main" \
|
||||||
|
> /etc/apt/sources.list.d/gazebo-stable.list \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
gz-harmonic
|
||||||
|
|
||||||
|
# Install PX4 files from .deb
|
||||||
|
COPY --from=extract /staging/opt/px4-gazebo /opt/px4-gazebo
|
||||||
|
RUN ln -sf /opt/px4-gazebo/bin/px4-gazebo /usr/bin/px4-gazebo
|
||||||
|
|
||||||
|
# Create the DART physics engine symlink (avoids needing the -dev package)
|
||||||
|
RUN GZ_PHYSICS_DIR=$(find /usr/lib -maxdepth 3 -type d -name "engine-plugins" -path "*/gz-physics-7/*" 2>/dev/null | head -1) \
|
||||||
|
&& if [ -n "$GZ_PHYSICS_DIR" ] && [ -d "$GZ_PHYSICS_DIR" ]; then \
|
||||||
|
VERSIONED=$(ls "$GZ_PHYSICS_DIR"/libgz-physics*-dartsim-plugin.so.* 2>/dev/null | head -1) \
|
||||||
|
&& [ -n "$VERSIONED" ] \
|
||||||
|
&& ln -sf "$(basename "$VERSIONED")" "$GZ_PHYSICS_DIR/libgz-physics-dartsim-plugin.so"; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Gazebo resource paths
|
||||||
|
ENV GZ_SIM_RESOURCE_PATH=/opt/px4-gazebo/share/gz/models:/opt/px4-gazebo/share/gz/worlds
|
||||||
|
ENV GZ_SIM_SYSTEM_PLUGIN_PATH=/opt/px4-gazebo/lib/gz/plugins
|
||||||
|
ENV GZ_SIM_SERVER_CONFIG_PATH=/opt/px4-gazebo/share/gz/server.config
|
||||||
|
ENV PX4_GZ_MODELS=/opt/px4-gazebo/share/gz/models
|
||||||
|
ENV PX4_GZ_WORLDS=/opt/px4-gazebo/share/gz/worlds
|
||||||
|
|
||||||
|
ENV PX4_SIM_MODEL=gz_x500
|
||||||
|
ENV HOME=/root
|
||||||
|
|
||||||
|
# MAVLink, MAVSDK, DDS
|
||||||
|
EXPOSE 14550/udp 14540/udp 8888/udp
|
||||||
|
|
||||||
|
# Platform-adaptive entrypoint: detects Docker Desktop (macOS/Windows) via
|
||||||
|
# host.docker.internal and configures MAVLink + DDS to target the host.
|
||||||
|
COPY px4-entrypoint.sh /opt/px4-gazebo/bin/px4-entrypoint.sh
|
||||||
|
RUN chmod +x /opt/px4-gazebo/bin/px4-entrypoint.sh
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
ENTRYPOINT ["/opt/px4-gazebo/bin/px4-entrypoint.sh"]
|
||||||
|
CMD []
|
||||||
49
Tools/packaging/Dockerfile.sih
Normal file
49
Tools/packaging/Dockerfile.sih
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
# PX4 SITL SIH runtime image
|
||||||
|
# Minimal container that runs PX4 with the SIH physics engine (no Gazebo).
|
||||||
|
#
|
||||||
|
# Build:
|
||||||
|
# make px4_sitl_sih && cd build/px4_sitl_sih && cpack -G DEB && cd ../..
|
||||||
|
# docker build -f Tools/packaging/Dockerfile.sih -t px4io/px4-sitl-sih:v1.17.0 build/px4_sitl_sih/
|
||||||
|
#
|
||||||
|
# Run (Linux):
|
||||||
|
# docker run --rm -it --network host px4io/px4-sitl-sih:v1.17.0
|
||||||
|
#
|
||||||
|
# Run (macOS / Windows):
|
||||||
|
# docker run --rm -it -p 14550:14550/udp -p 14540:14540/udp -p 19410:19410/udp -p 8888:8888/udp px4io/px4-sitl-sih:v1.17.0
|
||||||
|
|
||||||
|
FROM ubuntu:24.04 AS build
|
||||||
|
COPY px4_*.deb /tmp/
|
||||||
|
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||||
|
apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends binutils \
|
||||||
|
&& dpkg -x /tmp/px4_*.deb /staging \
|
||||||
|
&& strip /staging/opt/px4/bin/px4
|
||||||
|
|
||||||
|
FROM ubuntu:24.04
|
||||||
|
LABEL maintainer="PX4 Development Team"
|
||||||
|
LABEL description="PX4 SITL with SIH physics (no simulator dependencies)"
|
||||||
|
|
||||||
|
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/lib/apt,sharing=locked \
|
||||||
|
apt-get update && apt-get install -y --no-install-recommends bc
|
||||||
|
|
||||||
|
COPY --from=build /staging/opt/px4 /opt/px4
|
||||||
|
RUN ln -sf /opt/px4/bin/px4 /usr/bin/px4
|
||||||
|
|
||||||
|
# Platform-adaptive entrypoint: detects Docker Desktop (macOS/Windows) via
|
||||||
|
# host.docker.internal and configures MAVLink + DDS to target the host.
|
||||||
|
COPY px4-entrypoint.sh /opt/px4/bin/px4-entrypoint.sh
|
||||||
|
RUN chmod +x /opt/px4/bin/px4-entrypoint.sh
|
||||||
|
|
||||||
|
ENV PX4_SIM_MODEL=sihsim_quadx
|
||||||
|
ENV HOME=/root
|
||||||
|
|
||||||
|
# MAVLink (QGC, MAVSDK), DDS (ROS 2), jMAVSim/viewer display
|
||||||
|
EXPOSE 14550/udp 14540/udp 19410/udp 8888/udp
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
ENTRYPOINT ["/opt/px4/bin/px4-entrypoint.sh"]
|
||||||
|
CMD []
|
||||||
4
Tools/packaging/postinst
Executable file
4
Tools/packaging/postinst
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
ln -sf /opt/px4-gazebo/bin/px4-gazebo /usr/bin/px4-gazebo
|
||||||
|
exit 0
|
||||||
6
Tools/packaging/postrm
Executable file
6
Tools/packaging/postrm
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
|
||||||
|
rm -f /usr/bin/px4-gazebo
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
32
Tools/packaging/px4-entrypoint.sh
Normal file
32
Tools/packaging/px4-entrypoint.sh
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Docker entrypoint for PX4 SITL containers.
|
||||||
|
#
|
||||||
|
# On Docker Desktop (macOS/Windows), host.docker.internal resolves to the
|
||||||
|
# host machine. We detect this and configure MAVLink + DDS to send to the
|
||||||
|
# host IP instead of localhost (which stays inside the container VM).
|
||||||
|
#
|
||||||
|
# On Linux with --network host, host.docker.internal does not resolve and
|
||||||
|
# PX4 defaults work without modification.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Detect install prefix (SIH uses /opt/px4, Gazebo uses /opt/px4-gazebo)
|
||||||
|
if [ -d /opt/px4-gazebo ]; then
|
||||||
|
PX4_PREFIX=/opt/px4-gazebo
|
||||||
|
else
|
||||||
|
PX4_PREFIX=/opt/px4
|
||||||
|
fi
|
||||||
|
|
||||||
|
if getent hosts host.docker.internal >/dev/null 2>&1; then
|
||||||
|
DOCKER_HOST_IP=$(getent hosts host.docker.internal | awk '{print $1}')
|
||||||
|
|
||||||
|
# MAVLink: replace default target (127.0.0.1) with the Docker host IP
|
||||||
|
sed -i "s/mavlink start -x -u/mavlink start -x -t $DOCKER_HOST_IP -u/g" \
|
||||||
|
"$PX4_PREFIX/etc/init.d-posix/px4-rc.mavlink"
|
||||||
|
|
||||||
|
# DDS: point uXRCE-DDS client at the host
|
||||||
|
sed -i "s|uxrce_dds_client start -t udp|uxrce_dds_client start -t udp -h $DOCKER_HOST_IP|" \
|
||||||
|
"$PX4_PREFIX/etc/init.d-posix/rcS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$PX4_PREFIX/bin/px4" "$@"
|
||||||
32
Tools/packaging/px4-gazebo.sh
Normal file
32
Tools/packaging/px4-gazebo.sh
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# px4-gazebo: Launch PX4 SITL with Gazebo from the installed .deb package
|
||||||
|
set -e
|
||||||
|
|
||||||
|
PX4_GAZEBO_DIR="$(cd "$(dirname "$(readlink -f "$0")")/.." && pwd)"
|
||||||
|
PX4_BINARY="${PX4_GAZEBO_DIR}/bin/px4"
|
||||||
|
|
||||||
|
# Set Gazebo resource paths so gz-sim finds PX4 models, worlds, and plugins.
|
||||||
|
export PX4_GZ_MODELS="${PX4_GAZEBO_DIR}/share/gz/models"
|
||||||
|
export PX4_GZ_WORLDS="${PX4_GAZEBO_DIR}/share/gz/worlds"
|
||||||
|
export PX4_GZ_PLUGINS="${PX4_GAZEBO_DIR}/lib/gz/plugins"
|
||||||
|
export PX4_GZ_SERVER_CONFIG="${PX4_GAZEBO_DIR}/share/gz/server.config"
|
||||||
|
export GZ_SIM_RESOURCE_PATH="${GZ_SIM_RESOURCE_PATH}:${PX4_GZ_MODELS}:${PX4_GZ_WORLDS}"
|
||||||
|
export GZ_SIM_SYSTEM_PLUGIN_PATH="${GZ_SIM_SYSTEM_PLUGIN_PATH}:${PX4_GZ_PLUGINS}"
|
||||||
|
export GZ_SIM_SERVER_CONFIG_PATH="${PX4_GZ_SERVER_CONFIG}"
|
||||||
|
|
||||||
|
# Gazebo's Physics system searches for "gz-physics-dartsim-plugin" which maps
|
||||||
|
# to the unversioned libgz-physics-dartsim-plugin.so. The runtime package only
|
||||||
|
# ships versioned .so files; the unversioned symlink lives in the -dev package.
|
||||||
|
# Create it if missing so Gazebo finds the DART engine without installing -dev.
|
||||||
|
GZ_PHYSICS_ENGINE_DIR=$(find /usr/lib -maxdepth 3 -type d -name "engine-plugins" -path "*/gz-physics-7/*" 2>/dev/null | head -1)
|
||||||
|
if [ -n "$GZ_PHYSICS_ENGINE_DIR" ] && [ -d "$GZ_PHYSICS_ENGINE_DIR" ]; then
|
||||||
|
UNVERSIONED="$GZ_PHYSICS_ENGINE_DIR/libgz-physics-dartsim-plugin.so"
|
||||||
|
if [ ! -e "$UNVERSIONED" ]; then
|
||||||
|
VERSIONED=$(ls "$GZ_PHYSICS_ENGINE_DIR"/libgz-physics*-dartsim-plugin.so.* 2>/dev/null | head -1)
|
||||||
|
if [ -n "$VERSIONED" ]; then
|
||||||
|
ln -sf "$(basename "$VERSIONED")" "$UNVERSIONED" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "${PX4_BINARY}" "$@"
|
||||||
4
Tools/packaging/sih/postinst
Executable file
4
Tools/packaging/sih/postinst
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
ln -sf /opt/px4/bin/px4 /usr/bin/px4
|
||||||
|
exit 0
|
||||||
6
Tools/packaging/sih/postrm
Executable file
6
Tools/packaging/sih/postrm
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
|
||||||
|
rm -f /usr/bin/px4
|
||||||
|
fi
|
||||||
|
exit 0
|
||||||
144
Tools/packaging/test_sih_mission.py
Normal file
144
Tools/packaging/test_sih_mission.py
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
MAVSDK mission test for PX4 SIH SITL in Docker.
|
||||||
|
|
||||||
|
Takes off to 100m, flies a short 4-waypoint box mission, then lands.
|
||||||
|
Validates that the SIH Docker container works end-to-end with MAVSDK.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
- Docker container running:
|
||||||
|
docker run --rm --network host px4io/px4-sitl-sih:v1.17.0-alpha1
|
||||||
|
- pip install mavsdk
|
||||||
|
- mavsim-viewer running (optional):
|
||||||
|
/path/to/mavsim-viewer -n 1
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
python3 Tools/packaging/test_sih_mission.py
|
||||||
|
python3 Tools/packaging/test_sih_mission.py --speed 10 # faster-than-realtime
|
||||||
|
"""
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
from mavsdk import System
|
||||||
|
from mavsdk.mission import MissionItem, MissionPlan
|
||||||
|
|
||||||
|
|
||||||
|
async def run_mission(speed_factor: int = 1):
|
||||||
|
drone = System()
|
||||||
|
print(f"Connecting to drone on udp://:14540 ...")
|
||||||
|
await drone.connect(system_address="udp://:14540")
|
||||||
|
|
||||||
|
print("Waiting for drone to connect...")
|
||||||
|
async for state in drone.core.connection_state():
|
||||||
|
if state.is_connected:
|
||||||
|
print(f"Connected (UUID: {state.uuid if hasattr(state, 'uuid') else 'N/A'})")
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Waiting for global position estimate...")
|
||||||
|
async for health in drone.telemetry.health():
|
||||||
|
if health.is_global_position_ok and health.is_home_position_ok:
|
||||||
|
print("Global position OK")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Get home position for reference
|
||||||
|
async for pos in drone.telemetry.position():
|
||||||
|
home_lat = pos.latitude_deg
|
||||||
|
home_lon = pos.longitude_deg
|
||||||
|
print(f"Home position: {home_lat:.6f}, {home_lon:.6f}")
|
||||||
|
break
|
||||||
|
|
||||||
|
# Build a small box mission at 100m AGL
|
||||||
|
# ~100m offset in each direction
|
||||||
|
offset = 0.001 # roughly 111m at equator
|
||||||
|
mission_items = [
|
||||||
|
MissionItem(
|
||||||
|
home_lat + offset, home_lon,
|
||||||
|
100, 10, True, float('nan'), float('nan'),
|
||||||
|
MissionItem.CameraAction.NONE,
|
||||||
|
float('nan'), float('nan'), float('nan'),
|
||||||
|
float('nan'), float('nan'),
|
||||||
|
MissionItem.VehicleAction.NONE,
|
||||||
|
),
|
||||||
|
MissionItem(
|
||||||
|
home_lat + offset, home_lon + offset,
|
||||||
|
100, 10, True, float('nan'), float('nan'),
|
||||||
|
MissionItem.CameraAction.NONE,
|
||||||
|
float('nan'), float('nan'), float('nan'),
|
||||||
|
float('nan'), float('nan'),
|
||||||
|
MissionItem.VehicleAction.NONE,
|
||||||
|
),
|
||||||
|
MissionItem(
|
||||||
|
home_lat, home_lon + offset,
|
||||||
|
100, 10, True, float('nan'), float('nan'),
|
||||||
|
MissionItem.CameraAction.NONE,
|
||||||
|
float('nan'), float('nan'), float('nan'),
|
||||||
|
float('nan'), float('nan'),
|
||||||
|
MissionItem.VehicleAction.NONE,
|
||||||
|
),
|
||||||
|
MissionItem(
|
||||||
|
home_lat, home_lon,
|
||||||
|
100, 10, True, float('nan'), float('nan'),
|
||||||
|
MissionItem.CameraAction.NONE,
|
||||||
|
float('nan'), float('nan'), float('nan'),
|
||||||
|
float('nan'), float('nan'),
|
||||||
|
MissionItem.VehicleAction.NONE,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mission_plan = MissionPlan(mission_items)
|
||||||
|
|
||||||
|
print(f"Uploading mission ({len(mission_items)} waypoints, 100m AGL)...")
|
||||||
|
await drone.mission.upload_mission(mission_plan)
|
||||||
|
print("Mission uploaded")
|
||||||
|
|
||||||
|
print("Arming...")
|
||||||
|
await drone.action.arm()
|
||||||
|
print("Armed")
|
||||||
|
|
||||||
|
t0 = time.time()
|
||||||
|
print("Starting mission...")
|
||||||
|
await drone.mission.start_mission()
|
||||||
|
|
||||||
|
# Monitor mission progress
|
||||||
|
async for progress in drone.mission.mission_progress():
|
||||||
|
elapsed = time.time() - t0
|
||||||
|
print(f" [{elapsed:6.1f}s] Waypoint {progress.current}/{progress.total}")
|
||||||
|
if progress.current == progress.total:
|
||||||
|
print(f"Mission complete in {elapsed:.1f}s (speed factor: {speed_factor}x)")
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Returning to launch...")
|
||||||
|
await drone.action.return_to_launch()
|
||||||
|
|
||||||
|
# Wait for landing
|
||||||
|
async for in_air in drone.telemetry.in_air():
|
||||||
|
if not in_air:
|
||||||
|
print("Landed")
|
||||||
|
break
|
||||||
|
|
||||||
|
print("Disarming...")
|
||||||
|
await drone.action.disarm()
|
||||||
|
print("Test PASSED")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser(description="PX4 SIH Docker mission test")
|
||||||
|
parser.add_argument("--speed", type=int, default=1,
|
||||||
|
help="PX4_SIM_SPEED_FACTOR (must match container)")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
asyncio.run(run_mission(args.speed))
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
print("\nInterrupted")
|
||||||
|
sys.exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Test FAILED: {e}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@ -33,32 +33,24 @@
|
|||||||
|
|
||||||
# packaging
|
# packaging
|
||||||
|
|
||||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME}-${PX4_CONFIG})
|
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VENDOR "px4")
|
set(CPACK_PACKAGE_VENDOR "px4")
|
||||||
|
set(CPACK_PACKAGE_CONTACT "daniel@agar.ca")
|
||||||
|
set(CPACK_RESOURCE_FILE_LICENSE "${PX4_SOURCE_DIR}/LICENSE")
|
||||||
|
set(CPACK_RESOURCE_FILE_README "${PX4_SOURCE_DIR}/README.md")
|
||||||
|
|
||||||
|
set(CPACK_SOURCE_GENERATOR "ZIP;TBZ2")
|
||||||
|
|
||||||
|
# Debian version: convert git describe to Debian-compliant format
|
||||||
|
# v1.17.0-beta1 -> 1.17.0~beta1, v1.17.0 -> 1.17.0
|
||||||
|
string(REGEX REPLACE "^v" "" DEB_VERSION "${PX4_GIT_TAG}")
|
||||||
|
# Replace first hyphen with tilde for pre-release (Debian sorts ~ before anything)
|
||||||
|
string(REGEX REPLACE "^([0-9]+\\.[0-9]+\\.[0-9]+)-([a-zA-Z])" "\\1~\\2" DEB_VERSION "${DEB_VERSION}")
|
||||||
|
# Strip any trailing commit info (e.g. -42-gabcdef)
|
||||||
|
string(REGEX REPLACE "-[0-9]+-g[0-9a-f]+$" "" DEB_VERSION "${DEB_VERSION}")
|
||||||
|
|
||||||
set(CPACK_PACKAGE_VERSION_MAJOR ${PX4_VERSION_MAJOR})
|
set(CPACK_PACKAGE_VERSION_MAJOR ${PX4_VERSION_MAJOR})
|
||||||
set(CPACK_PACKAGE_VERSION_MINOR ${PX4_VERSION_MINOR})
|
set(CPACK_PACKAGE_VERSION_MINOR ${PX4_VERSION_MINOR})
|
||||||
set(CPACK_PACKAGE_VERSION_PATCH ${PX4_VERSION_PATCH})
|
set(CPACK_PACKAGE_VERSION_PATCH ${PX4_VERSION_PATCH})
|
||||||
#set(CPACK_PACKAGE_VERSION ${PX4_GIT_TAG})
|
|
||||||
|
|
||||||
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PX4_CONFIG}-${PX4_GIT_TAG}")
|
|
||||||
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PROJECT_NAME}-${PX4_CONFIG}-${PX4_GIT_TAG}-src")
|
|
||||||
|
|
||||||
set(CPACK_PACKAGE_CONTACT "daniel@agar.ca")
|
|
||||||
|
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${PX4_SOURCE_DIR}/LICENSE")
|
|
||||||
set(CPACK_RESOURCE_FILE_README "${PX4_SOURCE_DIR}/README.md")
|
|
||||||
|
|
||||||
set(CPACK_COMPONENTS_GROUPING ALL_COMPONENTS_IN_ONE)#ONE_PER_GROUP)
|
|
||||||
# without this you won't be able to pack only specified component
|
|
||||||
set(CPACK_DEB_COMPONENT_INSTALL YES)
|
|
||||||
|
|
||||||
#set(CPACK_STRIP_FILES YES)
|
|
||||||
|
|
||||||
set(CPACK_SOURCE_GENERATOR "ZIP;TBZ2")
|
|
||||||
set(CPACK_PACKAGING_INSTALL_PREFIX "")
|
|
||||||
set(CPACK_SET_DESTDIR "OFF")
|
|
||||||
|
|
||||||
if("${CMAKE_SYSTEM}" MATCHES "Linux")
|
if("${CMAKE_SYSTEM}" MATCHES "Linux")
|
||||||
set(CPACK_GENERATOR "TBZ2")
|
set(CPACK_GENERATOR "TBZ2")
|
||||||
@ -67,30 +59,61 @@ if("${CMAKE_SYSTEM}" MATCHES "Linux")
|
|||||||
if(EXISTS ${DPKG_PROGRAM})
|
if(EXISTS ${DPKG_PROGRAM})
|
||||||
list(APPEND CPACK_GENERATOR "DEB")
|
list(APPEND CPACK_GENERATOR "DEB")
|
||||||
|
|
||||||
set(CPACK_SET_DESTDIR true)
|
execute_process(COMMAND ${DPKG_PROGRAM} --print-architecture
|
||||||
set(CPACK_PACKAGING_INSTALL_PREFIX "/tmp")
|
OUTPUT_VARIABLE DEB_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
execute_process(COMMAND ${DPKG_PROGRAM} --print-architecture OUTPUT_VARIABLE DEB_ARCHITECTURE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
# Detect Ubuntu/Debian codename for version suffix
|
||||||
message("Architecture: " ${DEB_ARCHITECTURE})
|
find_program(LSB_RELEASE lsb_release)
|
||||||
set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}_${DEB_ARCHITECTURE}")
|
if(EXISTS ${LSB_RELEASE})
|
||||||
|
execute_process(COMMAND ${LSB_RELEASE} -cs
|
||||||
|
OUTPUT_VARIABLE DEB_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
else()
|
||||||
|
set(DEB_CODENAME "unknown")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CPACK_INSTALL_PREFIX @DEB_INSTALL_PREFIX@)
|
# Override CPACK_PACKAGE_VERSION with full Debian version.
|
||||||
message ("==> CPACK_INSTALL_PREFIX = " ${CPACK_INSTALL_PREFIX})
|
# CPack DEB ignores CPACK_PACKAGE_VERSION_MAJOR/MINOR/PATCH
|
||||||
|
# when CPACK_PACKAGE_VERSION is set, so we must replace them.
|
||||||
|
unset(CPACK_PACKAGE_VERSION_MAJOR)
|
||||||
|
unset(CPACK_PACKAGE_VERSION_MINOR)
|
||||||
|
unset(CPACK_PACKAGE_VERSION_PATCH)
|
||||||
|
set(CPACK_PACKAGE_VERSION "${DEB_VERSION}-${DEB_CODENAME}")
|
||||||
|
|
||||||
################################################################################
|
# Label-aware package metadata
|
||||||
|
if(PX4_BOARD_LABEL STREQUAL "sih")
|
||||||
|
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/px4")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_NAME "px4")
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "px4_${DEB_VERSION}-${DEB_CODENAME}_${DEB_ARCHITECTURE}.deb")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "PX4 SITL autopilot with SIH physics (no Gazebo)")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||||
|
"${PX4_SOURCE_DIR}/Tools/packaging/sih/postinst;${PX4_SOURCE_DIR}/Tools/packaging/sih/postrm")
|
||||||
|
else()
|
||||||
|
set(CPACK_PACKAGING_INSTALL_PREFIX "/opt/px4-gazebo")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_NAME "px4-gazebo")
|
||||||
|
set(CPACK_DEBIAN_FILE_NAME "px4-gazebo_${DEB_VERSION}-${DEB_CODENAME}_${DEB_ARCHITECTURE}.deb")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6, libstdc++6, gz-sim8-cli, libgz-sim8-plugins, libgz-physics7-dartsim, gz-tools2")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "PX4 SITL autopilot with Gazebo Harmonic simulation resources")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA
|
||||||
|
"${PX4_SOURCE_DIR}/Tools/packaging/postinst;${PX4_SOURCE_DIR}/Tools/packaging/postrm")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Daniel Agar <${CPACK_PACKAGE_CONTACT}>")
|
# Bake the install prefix into the px4 binary so it can locate its ROMFS
|
||||||
set(CPACK_DEBIAN_PACKAGE_VERSION ${CPACK_PACKAGE_VERSION})
|
# (etc/) without a wrapper script or command-line argument.
|
||||||
set(CPACK_DEBIAN_FILE_NAME DEB-DEFAULT)
|
if(TARGET px4)
|
||||||
|
target_compile_definitions(px4 PRIVATE PX4_INSTALL_PREFIX="${CPACK_PACKAGING_INSTALL_PREFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_DESCRIPTION "PX4 autopilot")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SECTION "misc")
|
set(CPACK_DEBIAN_PACKAGE_SECTION "misc")
|
||||||
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR})
|
set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE ${DEB_ARCHITECTURE})
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
|
||||||
|
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Daniel Agar <${CPACK_PACKAGE_CONTACT}>")
|
||||||
|
|
||||||
# autogenerate dependency information
|
|
||||||
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS ON)
|
||||||
set(CPACK_DEBIAN_COMPRESSION_TYPE xz)
|
set(CPACK_DEBIAN_COMPRESSION_TYPE xz)
|
||||||
|
set(CPACK_DEBIAN_ARCHITECTURE ${DEB_ARCHITECTURE})
|
||||||
|
|
||||||
|
message(STATUS "PX4 SITL .deb version: ${DEB_VERSION}-${DEB_CODENAME} (${DEB_ARCHITECTURE})")
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
else()
|
else()
|
||||||
|
|||||||
@ -23,6 +23,9 @@ px4_posix_generate_alias(
|
|||||||
|
|
||||||
add_definitions(-DPX4_SOURCE_DIR="${PX4_SOURCE_DIR}" -DPX4_BINARY_DIR="${PX4_BINARY_DIR}")
|
add_definitions(-DPX4_SOURCE_DIR="${PX4_SOURCE_DIR}" -DPX4_BINARY_DIR="${PX4_BINARY_DIR}")
|
||||||
|
|
||||||
|
# PX4_INSTALL_PREFIX is set by cmake/package.cmake after this file is processed.
|
||||||
|
# It is passed via target_compile_definitions on the px4 target from package.cmake.
|
||||||
|
|
||||||
add_executable(px4
|
add_executable(px4
|
||||||
src/px4/common/main.cpp
|
src/px4/common/main.cpp
|
||||||
apps.cpp
|
apps.cpp
|
||||||
@ -80,10 +83,16 @@ target_link_libraries(px4 PRIVATE uORB)
|
|||||||
# install
|
# install
|
||||||
#
|
#
|
||||||
|
|
||||||
|
# Detect dpkg early so install rules can branch on it.
|
||||||
|
# find_program caches the result, so the later call in package.cmake is a no-op.
|
||||||
|
find_program(DPKG_PROGRAM dpkg)
|
||||||
|
|
||||||
# Generic install rules (skipped when board provides its own install.cmake)
|
# Generic install rules (skipped when board provides its own install.cmake)
|
||||||
if(NOT EXISTS "${PX4_BOARD_DIR}/cmake/install.cmake")
|
if(NOT EXISTS "${PX4_BOARD_DIR}/cmake/install.cmake")
|
||||||
|
|
||||||
# px4 dirs
|
# Legacy top-level install (posix-configs, test data, etc into px4/ prefix).
|
||||||
|
# Skip when building .deb packages which use a clean /opt/px4-sitl{,-sih}/ layout.
|
||||||
|
if(NOT DPKG_PROGRAM)
|
||||||
install(
|
install(
|
||||||
DIRECTORY
|
DIRECTORY
|
||||||
${PROJECT_SOURCE_DIR}/posix-configs
|
${PROJECT_SOURCE_DIR}/posix-configs
|
||||||
@ -94,6 +103,7 @@ install(
|
|||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
USE_SOURCE_PERMISSIONS
|
USE_SOURCE_PERMISSIONS
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
endif() # NOT board install.cmake
|
endif() # NOT board install.cmake
|
||||||
|
|
||||||
@ -163,6 +173,11 @@ elseif("${PX4_BOARD}" MATCHES "sitl")
|
|||||||
|
|
||||||
# install
|
# install
|
||||||
|
|
||||||
|
# Legacy install rules (used by ROS launch, existing CPack tarball workflow).
|
||||||
|
# Skip when building .deb packages: the .deb rules below provide a clean
|
||||||
|
# /opt/px4-sitl{,-sih}/ layout and these would duplicate/bloat the package.
|
||||||
|
if(NOT DPKG_PROGRAM)
|
||||||
|
|
||||||
# px4 dirs
|
# px4 dirs
|
||||||
install(
|
install(
|
||||||
DIRECTORY
|
DIRECTORY
|
||||||
@ -227,4 +242,82 @@ elseif("${PX4_BOARD}" MATCHES "sitl")
|
|||||||
OPTIONAL
|
OPTIONAL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
endif() # NOT DPKG_PROGRAM
|
||||||
|
|
||||||
|
####################################################################
|
||||||
|
# Install rules for .deb package (only when dpkg is available)
|
||||||
|
####################################################################
|
||||||
|
if(DPKG_PROGRAM AND NOT CMAKE_C_COMPILER MATCHES "emcc$")
|
||||||
|
|
||||||
|
# px4 binary
|
||||||
|
install(TARGETS px4
|
||||||
|
RUNTIME DESTINATION bin
|
||||||
|
)
|
||||||
|
|
||||||
|
# module symlinks and alias script
|
||||||
|
install(
|
||||||
|
DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/
|
||||||
|
DESTINATION bin
|
||||||
|
USE_SOURCE_PERMISSIONS
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "px4-*"
|
||||||
|
PATTERN "px4-alias.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ROMFS (init scripts, mixers, etc.)
|
||||||
|
install(
|
||||||
|
DIRECTORY ${PX4_BINARY_DIR}/etc
|
||||||
|
DESTINATION .
|
||||||
|
USE_SOURCE_PERMISSIONS
|
||||||
|
)
|
||||||
|
|
||||||
|
if(CONFIG_MODULES_SIMULATION_GZ_BRIDGE)
|
||||||
|
# Gazebo wrapper script (sets GZ_SIM_* env vars pointing at installed resources)
|
||||||
|
install(
|
||||||
|
PROGRAMS ${PROJECT_SOURCE_DIR}/Tools/packaging/px4-gazebo.sh
|
||||||
|
DESTINATION bin
|
||||||
|
RENAME px4-gazebo
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CONFIG_MODULES_SIMULATION_GZ_BRIDGE)
|
||||||
|
# Gazebo models
|
||||||
|
install(
|
||||||
|
DIRECTORY ${PROJECT_SOURCE_DIR}/Tools/simulation/gz/models
|
||||||
|
DESTINATION share/gz
|
||||||
|
OPTIONAL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Gazebo worlds
|
||||||
|
install(
|
||||||
|
DIRECTORY ${PROJECT_SOURCE_DIR}/Tools/simulation/gz/worlds
|
||||||
|
DESTINATION share/gz
|
||||||
|
OPTIONAL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Gazebo server config
|
||||||
|
install(
|
||||||
|
FILES ${PROJECT_SOURCE_DIR}/Tools/simulation/gz/server.config
|
||||||
|
DESTINATION share/gz
|
||||||
|
OPTIONAL
|
||||||
|
)
|
||||||
|
|
||||||
|
# Gazebo plugins (built .so files)
|
||||||
|
install(
|
||||||
|
DIRECTORY ${CMAKE_BINARY_DIR}/src/modules/simulation/gz_plugins/
|
||||||
|
DESTINATION lib/gz/plugins
|
||||||
|
FILES_MATCHING PATTERN "*.so"
|
||||||
|
PATTERN "CMakeFiles" EXCLUDE
|
||||||
|
)
|
||||||
|
|
||||||
|
# OpticalFlow external library (runtime dep of OpticalFlowSystem plugin)
|
||||||
|
install(
|
||||||
|
FILES ${CMAKE_BINARY_DIR}/OpticalFlow/install/lib/libOpticalFlow.so
|
||||||
|
DESTINATION lib/gz/plugins
|
||||||
|
OPTIONAL
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif() # DPKG_PROGRAM AND NOT emcc
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@ -259,6 +259,32 @@ int main(int argc, char **argv)
|
|||||||
PX4_INFO("instance: %i", instance);
|
PX4_INFO("instance: %i", instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(PX4_INSTALL_PREFIX)
|
||||||
|
|
||||||
|
// When installed as a .deb package, default to the baked-in install prefix.
|
||||||
|
// Working directory defaults to XDG_DATA_HOME/px4/rootfs/<instance>.
|
||||||
|
if (commands_file.empty() && data_path.empty() && working_directory.empty()
|
||||||
|
&& dir_exists(PX4_INSTALL_PREFIX"/etc")
|
||||||
|
) {
|
||||||
|
data_path = PX4_INSTALL_PREFIX"/etc";
|
||||||
|
|
||||||
|
const char *xdg_data_home = getenv("XDG_DATA_HOME");
|
||||||
|
std::string state_base;
|
||||||
|
|
||||||
|
if (xdg_data_home) {
|
||||||
|
state_base = xdg_data_home;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
const char *home = getenv("HOME");
|
||||||
|
state_base = std::string(home ? home : "/tmp") + "/.local/share";
|
||||||
|
}
|
||||||
|
|
||||||
|
working_directory = state_base + "/px4/rootfs";
|
||||||
|
working_directory_default = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // PX4_INSTALL_PREFIX
|
||||||
|
|
||||||
#if defined(PX4_BINARY_DIR)
|
#if defined(PX4_BINARY_DIR)
|
||||||
|
|
||||||
// data_path & working_directory: if no commands specified or in current working directory),
|
// data_path & working_directory: if no commands specified or in current working directory),
|
||||||
@ -745,13 +771,34 @@ std::string pwd()
|
|||||||
return (getcwd(temp, PATH_MAX) ? std::string(temp) : std::string(""));
|
return (getcwd(temp, PATH_MAX) ? std::string(temp) : std::string(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mkdir_p(const std::string &path)
|
||||||
|
{
|
||||||
|
std::string tmp = path;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < tmp.size(); ++i) {
|
||||||
|
if (tmp[i] == '/') {
|
||||||
|
tmp[i] = '\0';
|
||||||
|
|
||||||
|
if (mkdir(tmp.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0 && errno != EEXIST) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp[i] = '/';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mkdir(tmp.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0 && errno != EEXIST) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int change_directory(const std::string &directory)
|
int change_directory(const std::string &directory)
|
||||||
{
|
{
|
||||||
// create directory
|
// create directory (including intermediate components)
|
||||||
if (!dir_exists(directory)) {
|
if (!dir_exists(directory)) {
|
||||||
int ret = mkdir(directory.c_str(), S_IRWXU | S_IRWXG | S_IRWXO);
|
if (mkdir_p(directory) != 0) {
|
||||||
|
|
||||||
if (ret == -1) {
|
|
||||||
PX4_ERR("Error creating directory: %s (%s)", directory.c_str(), strerror(errno));
|
PX4_ERR("Error creating directory: %s (%s)", directory.c_str(), strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -64,6 +64,13 @@ target_include_directories(${PROJECT_NAME}
|
|||||||
|
|
||||||
add_dependencies(${PROJECT_NAME} OpticalFlow)
|
add_dependencies(${PROJECT_NAME} OpticalFlow)
|
||||||
|
|
||||||
|
# Add $ORIGIN to RPATH so the plugin finds libOpticalFlow.so in its own
|
||||||
|
# directory when installed (the packaging copies both .so files together).
|
||||||
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
||||||
|
BUILD_RPATH "$ORIGIN;${OPTICAL_FLOW_INSTALL_PREFIX}/lib"
|
||||||
|
INSTALL_RPATH "$ORIGIN"
|
||||||
|
)
|
||||||
|
|
||||||
if (NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
if (NOT CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||||
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib/px4_gz_plugins)
|
install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib/px4_gz_plugins)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user