intial stuff
This commit is contained in:
53
.devcontainer/devcontainer.json
Normal file
53
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"image": "ubuntu:24.04", // for cuda support: nvidia/cuda:13.1.0-devel-ubuntu24.04
|
||||||
|
"containerEnv": {
|
||||||
|
"CONAN_USR": "t", // need to be filled
|
||||||
|
"CONAN_PSW": "" // need to be filled,
|
||||||
|
},
|
||||||
|
"features": {
|
||||||
|
"ghcr.io/devcontainers/features/git:1": {},
|
||||||
|
"ghcr.io/devcontainers/features/git-lfs:1": {}
|
||||||
|
},
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"settings": {
|
||||||
|
"git.path": "/usr/bin/git"
|
||||||
|
},
|
||||||
|
"extensions": [
|
||||||
|
"ms-python.python",
|
||||||
|
"ms-python.vscode-pylance",
|
||||||
|
"GitHub.copilot-chat",
|
||||||
|
"njqdev.vscode-python-typehint",
|
||||||
|
"ms-python.debugpy",
|
||||||
|
"mhutchie.git-graph",
|
||||||
|
"ms-vscode.cpptools-themes",
|
||||||
|
"tamasfe.even-better-toml",
|
||||||
|
"moshfeu.compare-folders",
|
||||||
|
"njpwerner.autodocstring",
|
||||||
|
"ms-python.black-formatter",
|
||||||
|
"ms-python.isort",
|
||||||
|
"ms-vscode.live-server",
|
||||||
|
"yzhang.markdown-all-in-one",
|
||||||
|
"bierner.markdown-mermaid",
|
||||||
|
"charliermarsh.ruff",
|
||||||
|
"shardulm94.trailing-spaces",
|
||||||
|
"redhat.vscode-yaml",
|
||||||
|
"ninoseki.vscode-mogami",
|
||||||
|
"josetr.cmake-language-support-vscode",
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
|
"twxs.cmake",
|
||||||
|
"cheshirekow.cmake-format",
|
||||||
|
"ms-azuretools.vscode-docker",
|
||||||
|
"foxundermoon.shell-format",
|
||||||
|
"nvidia.nsight-vscode-edition"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runArgs": [
|
||||||
|
"--network=host",
|
||||||
|
"-e HOST_UID=$(id -u)",
|
||||||
|
"-e HOST_GID=$(id -g)",
|
||||||
|
"--gpus=all"
|
||||||
|
],
|
||||||
|
"postStartCommand": ".devcontainer/postStartCommand.sh"
|
||||||
|
}
|
||||||
186
.devcontainer/postStartCommand.sh
Executable file
186
.devcontainer/postStartCommand.sh
Executable file
@@ -0,0 +1,186 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
# Conan2 Development Environment Setup
|
||||||
|
#
|
||||||
|
# Description: Provisions system dependencies, shell configuration, and Conan2.
|
||||||
|
# Designed for Debian/Ubuntu-based DevContainers or CI Runners.
|
||||||
|
# Usage: CONAN_USR=x CONAN_PSW=y ./postStartCommand.sh
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# --- Configuration ------------------------------------------------------------
|
||||||
|
# Versions & Remote Resources
|
||||||
|
TASK_VERSION="v3.45.5"
|
||||||
|
GLOW_VERSION="2.1.1"
|
||||||
|
CONAN_CONFIG_URL="https://package-cloud.dns.army/ros2/conan2-config.git"
|
||||||
|
CONAN_REMOTE_NAME="package-cloud-ros2-conan2"
|
||||||
|
|
||||||
|
# Localization
|
||||||
|
TIMEZONE="Europe/Berlin"
|
||||||
|
|
||||||
|
# Paths
|
||||||
|
LOCAL_BIN="$HOME/.local/bin"
|
||||||
|
ZSH_CUSTOM="${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}"
|
||||||
|
|
||||||
|
# --- Helpers ------------------------------------------------------------------
|
||||||
|
|
||||||
|
log() {
|
||||||
|
echo -e "\033[1;34m>>> [SETUP] $1\033[0m"
|
||||||
|
}
|
||||||
|
|
||||||
|
error() {
|
||||||
|
echo -e "\033[1;31m!!! [ERROR] $1\033[0m" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
# Remove temp files on exit (successful or not)
|
||||||
|
rm -f glow.deb install_task.sh
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
ensure_env_vars() {
|
||||||
|
if [[ -z "${CONAN_USR:-}" ]] || [[ -z "${CONAN_PSW:-}" ]]; then
|
||||||
|
error "CONAN_USR and CONAN_PSW environment variables are required."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
detect_arch() {
|
||||||
|
local arch
|
||||||
|
arch=$(dpkg --print-architecture)
|
||||||
|
case "$arch" in
|
||||||
|
amd64) echo "amd64" ;;
|
||||||
|
arm64) echo "arm64" ;;
|
||||||
|
*) error "Unsupported architecture: $arch" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Installation Functions ---------------------------------------------------
|
||||||
|
|
||||||
|
install_system_dependencies() {
|
||||||
|
log "Installing system dependencies..."
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
apt-get update -q
|
||||||
|
apt-get install -y -q --no-install-recommends \
|
||||||
|
tzdata curl git zsh python3 python3-pip python3-venv \
|
||||||
|
ca-certificates gnupg pipx
|
||||||
|
|
||||||
|
# Ensure pipx path is available immediately for this script
|
||||||
|
export PATH="$LOCAL_BIN:$PATH"
|
||||||
|
pipx ensurepath
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_timezone() {
|
||||||
|
log "Configuring timezone ($TIMEZONE)..."
|
||||||
|
local tz_path="/usr/share/zoneinfo/$TIMEZONE"
|
||||||
|
|
||||||
|
# Validation: Ensure the requested timezone actually exists
|
||||||
|
if [ ! -f "$tz_path" ]; then
|
||||||
|
error "Timezone data not found at '$tz_path'. Please check the TIMEZONE variable."
|
||||||
|
fi
|
||||||
|
|
||||||
|
ln -fs "$tz_path" /etc/localtime
|
||||||
|
echo "$TIMEZONE" >/etc/timezone
|
||||||
|
dpkg-reconfigure -f noninteractive tzdata
|
||||||
|
}
|
||||||
|
|
||||||
|
install_shell_tools() {
|
||||||
|
log "Setting up Shell (Oh My Zsh)..."
|
||||||
|
if [ ! -d "$HOME/.oh-my-zsh" ]; then
|
||||||
|
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended
|
||||||
|
else
|
||||||
|
log "Oh My Zsh already installed. Skipping."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
install_conan() {
|
||||||
|
log "Installing Conan via pipx (Isolated)..."
|
||||||
|
|
||||||
|
# Use pipx to avoid breaking system packages
|
||||||
|
if ! command -v conan &>/dev/null; then
|
||||||
|
pipx install conan
|
||||||
|
else
|
||||||
|
pipx upgrade conan
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Config
|
||||||
|
log "Installing Conan Config..."
|
||||||
|
# Force allows overwriting existing configs which is usually desired in setup scripts
|
||||||
|
conan config install "$CONAN_CONFIG_URL" --type git --args="--branch main"
|
||||||
|
|
||||||
|
log "Authenticating Conan..."
|
||||||
|
conan remote login "$CONAN_REMOTE_NAME" "$CONAN_USR" -p "$CONAN_PSW"
|
||||||
|
}
|
||||||
|
|
||||||
|
install_utilities() {
|
||||||
|
local arch
|
||||||
|
arch=$(detect_arch)
|
||||||
|
|
||||||
|
# 1. Taskfile
|
||||||
|
log "Installing Taskfile ($TASK_VERSION)..."
|
||||||
|
curl -sL -o install_task.sh https://taskfile.dev/install.sh
|
||||||
|
sh install_task.sh -d -b "$LOCAL_BIN" "$TASK_VERSION"
|
||||||
|
|
||||||
|
# 2. Glow
|
||||||
|
log "Installing Glow ($GLOW_VERSION for $arch)..."
|
||||||
|
local glow_url="https://github.com/charmbracelet/glow/releases/download/v${GLOW_VERSION}/glow_${GLOW_VERSION}_${arch}.deb"
|
||||||
|
|
||||||
|
curl -L -o glow.deb "$glow_url"
|
||||||
|
dpkg -i glow.deb
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_persistence() {
|
||||||
|
log "Persisting configurations..."
|
||||||
|
|
||||||
|
local zshrc="$HOME/.zshrc"
|
||||||
|
touch "$zshrc"
|
||||||
|
|
||||||
|
# Helper to append if missing
|
||||||
|
append_if_missing() {
|
||||||
|
local file="$1"
|
||||||
|
local content="$2"
|
||||||
|
if ! grep -Fxq "$content" "$file"; then
|
||||||
|
echo "$content" >>"$file"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Add Local Bin to Path
|
||||||
|
append_if_missing "$HOME/.bashrc" "$path_export"
|
||||||
|
append_if_missing "$zshrc" "$path_export"
|
||||||
|
|
||||||
|
# Shell Completions
|
||||||
|
append_if_missing "$zshrc" 'eval "$(task --completion zsh)"'
|
||||||
|
append_if_missing "$zshrc" 'eval "$(glow completion zsh)"'
|
||||||
|
|
||||||
|
# Git Safe Directory
|
||||||
|
git config --global --add safe.directory /workspaces/conan2-ros2-video-to-rosbag
|
||||||
|
}
|
||||||
|
|
||||||
|
run_tasks() {
|
||||||
|
if [ -f "Taskfile.yml" ] || [ -f "Taskfile.yaml" ]; then
|
||||||
|
log "Running default Task..."
|
||||||
|
"$LOCAL_BIN/task" --yes
|
||||||
|
else
|
||||||
|
log "No Taskfile found. Skipping 'task --yes'."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Main Execution -----------------------------------------------------------
|
||||||
|
|
||||||
|
main() {
|
||||||
|
ensure_env_vars
|
||||||
|
install_system_dependencies
|
||||||
|
configure_timezone
|
||||||
|
install_shell_tools
|
||||||
|
install_utilities # Task & Glow
|
||||||
|
install_conan # Depends on pipx (sys deps)
|
||||||
|
configure_persistence
|
||||||
|
run_tasks
|
||||||
|
|
||||||
|
log "Setup complete successfully."
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
3
.taskrc.yml
Normal file
3
.taskrc.yml
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Enable experimental features
|
||||||
|
experiments:
|
||||||
|
REMOTE_TASKFILES: 1
|
||||||
14
LICENSE
Normal file
14
LICENSE
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
Copyright (C) 2023 Hesai Technology Co., Ltd.
|
||||||
|
Copyright (C) 2023 Hesai Technology, zhangyu
|
||||||
|
Copyright (C) 2023 Hesai Technology, huangzhongbo
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
All code in this repository is released under the terms of the following Modified BSD License. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
* Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
181
Taskfile.hesai.yml
Normal file
181
Taskfile.hesai.yml
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
|
||||||
|
# https://taskfile.dev
|
||||||
|
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
BUILD_TYPE: '{{.BUILD_TYPE | default "Release"}}'
|
||||||
|
VERSION: '{{.CONAN_BUILD_VERSION | default .ENV_CONAN_BUILD_VERSION | default "0.0.0-dev"}}'
|
||||||
|
# Detect System Architecture (x86_64 or aarch64)
|
||||||
|
SYSTEM_ARCH:
|
||||||
|
sh: arch
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
# ============================================================================
|
||||||
|
# Core Logic (Internal)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
_validate_arch:
|
||||||
|
internal: true
|
||||||
|
silent: true
|
||||||
|
desc: "Checks if the current system architecture supports the requested build"
|
||||||
|
requires:
|
||||||
|
vars: [EXPECTED_ARCH]
|
||||||
|
cmds:
|
||||||
|
- |
|
||||||
|
if [ "{{.SYSTEM_ARCH}}" != "{{.EXPECTED_ARCH}}" ]; then
|
||||||
|
echo "❌ ARCHITECTURE MISMATCH ERROR:"
|
||||||
|
echo " - System Arch: {{.SYSTEM_ARCH}}"
|
||||||
|
echo " - Expected Arch: {{.EXPECTED_ARCH}}"
|
||||||
|
echo " - Task Type: Native Build"
|
||||||
|
echo ""
|
||||||
|
echo " You are trying to run a 'native' build for {{.EXPECTED_ARCH}} on a {{.SYSTEM_ARCH}} machine."
|
||||||
|
echo " Please use the 'cross-...' task instead."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo "✅ Architecture match: System={{.SYSTEM_ARCH}} matches Target={{.EXPECTED_ARCH}}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_create:
|
||||||
|
internal: true
|
||||||
|
desc: "Core wrapper for conan create"
|
||||||
|
requires:
|
||||||
|
vars: [PROFILE_HOST, PROFILE_BUILD]
|
||||||
|
cmds:
|
||||||
|
- >-
|
||||||
|
conan create .
|
||||||
|
--profile:build {{.PROFILE_BUILD}}
|
||||||
|
--profile:host {{.PROFILE_HOST}}
|
||||||
|
--build=missing
|
||||||
|
--version {{.VERSION}}
|
||||||
|
-s build_type={{.BUILD_TYPE}}
|
||||||
|
|
||||||
|
_create_with_cuda:
|
||||||
|
internal: true
|
||||||
|
desc: "Core wrapper for conan create"
|
||||||
|
requires:
|
||||||
|
vars: [PROFILE_HOST, PROFILE_BUILD]
|
||||||
|
cmds:
|
||||||
|
- >-
|
||||||
|
conan create .
|
||||||
|
--profile:build {{.PROFILE_BUILD}}
|
||||||
|
--profile:host {{.PROFILE_HOST}}
|
||||||
|
--build=missing
|
||||||
|
--version {{.VERSION}}
|
||||||
|
-s build_type={{.BUILD_TYPE}}
|
||||||
|
-o with_cuda=True
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# GCC 13 (Modern)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
native-x64:gcc13:
|
||||||
|
desc: "Build: Native x64 (GCC 13)"
|
||||||
|
cmds:
|
||||||
|
# x86_64 is the standard output of 'arch' for Intel/AMD
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "x86_64" }
|
||||||
|
- task: _create
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: x64_linux_gcc_13
|
||||||
|
PROFILE_HOST: x64_linux_gcc_13
|
||||||
|
|
||||||
|
native-x64:gcc13:cuda:
|
||||||
|
desc: "Build: Native x64 (GCC 13) with cuda support"
|
||||||
|
cmds:
|
||||||
|
# x86_64 is the standard output of 'arch' for Intel/AMD
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "x86_64" }
|
||||||
|
- task: _create_with_cuda
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: x64_linux_gcc_13
|
||||||
|
PROFILE_HOST: x64_linux_gcc_13
|
||||||
|
|
||||||
|
native-armv8:gcc13:
|
||||||
|
desc: "Build: Native ARMv8 (GCC 13)"
|
||||||
|
cmds:
|
||||||
|
# aarch64 is the standard output of 'arch' for ARMv8
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "aarch64" }
|
||||||
|
- task: _create
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: armv8_linux_gcc_13
|
||||||
|
PROFILE_HOST: armv8_linux_gcc_13
|
||||||
|
|
||||||
|
native-armv8:gcc13:cuda:
|
||||||
|
desc: "Build: Native ARMv8 (GCC 13) with cuda support"
|
||||||
|
cmds:
|
||||||
|
# aarch64 is the standard output of 'arch' for ARMv8
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "aarch64" }
|
||||||
|
- task: _create_with_cuda
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: armv8_linux_gcc_13
|
||||||
|
PROFILE_HOST: armv8_linux_gcc_13
|
||||||
|
|
||||||
|
cross-armv8:gcc13:
|
||||||
|
desc: "Build: Cross-Compile x64 -> ARMv8 (GCC 13)"
|
||||||
|
cmds:
|
||||||
|
# No validation needed for Cross-Compilation, as mismatch is intended
|
||||||
|
- echo "⚠️ Cross-compiling for ARMv8 on {{.SYSTEM_ARCH}} (No arch check enforced)"
|
||||||
|
- task: _create
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: x64_linux_gcc_13
|
||||||
|
PROFILE_HOST: armv8_linux_gcc_13_croco
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# GCC 9 (Legacy)
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
native-x64:gcc9:
|
||||||
|
desc: "Build: Native x64 (GCC 9)"
|
||||||
|
cmds:
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "x86_64" }
|
||||||
|
- task: _create
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: x64_linux_gcc_9
|
||||||
|
PROFILE_HOST: x64_linux_gcc_9
|
||||||
|
|
||||||
|
native-x64:gcc9:cuda:
|
||||||
|
desc: "Build: Native x64 (GCC 9) with cuda support"
|
||||||
|
cmds:
|
||||||
|
# x86_64 is the standard output of 'arch' for Intel/AMD
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "x86_64" }
|
||||||
|
- task: _create_with_cuda
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: x64_linux_gcc_9
|
||||||
|
PROFILE_HOST: x64_linux_gcc_9
|
||||||
|
|
||||||
|
|
||||||
|
native-armv8:gcc9:
|
||||||
|
desc: "Build: Native ARMv8 (GCC 9)"
|
||||||
|
cmds:
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "aarch64" }
|
||||||
|
- task: _create
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: armv8_linux_gcc_9
|
||||||
|
PROFILE_HOST: armv8_linux_gcc_9
|
||||||
|
|
||||||
|
native-armv8:gcc9:cuda:
|
||||||
|
desc: "Build: Native ARMv8 (GCC 9) with cuda support"
|
||||||
|
cmds:
|
||||||
|
# aarch64 is the standard output of 'arch' for ARMv8
|
||||||
|
- task: _validate_arch
|
||||||
|
vars: { EXPECTED_ARCH: "aarch64" }
|
||||||
|
- task: _create_with_cuda
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: armv8_linux_gcc_9
|
||||||
|
PROFILE_HOST: armv8_linux_gcc_9
|
||||||
|
|
||||||
|
cross-armv8:gcc9:
|
||||||
|
desc: "Build: Cross-Compile x64 -> ARMv8 (GCC 9)"
|
||||||
|
cmds:
|
||||||
|
- echo "⚠️ Cross-compiling for ARMv8 on {{.SYSTEM_ARCH}} (No arch check enforced)"
|
||||||
|
- task: _create
|
||||||
|
vars:
|
||||||
|
PROFILE_BUILD: x64_linux_gcc_9
|
||||||
|
PROFILE_HOST: armv8_linux_gcc_9_croco
|
||||||
47
Taskfile.yml
Normal file
47
Taskfile.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# https://taskfile.dev
|
||||||
|
|
||||||
|
version: "3"
|
||||||
|
|
||||||
|
vars:
|
||||||
|
# Global Configuration
|
||||||
|
CONAN2_CONFIG_URL: https://package-cloud.dns.army/ros2/conan2-config
|
||||||
|
CONAN2_CONFIG_BRANCH: main
|
||||||
|
CONAN2_CONFIG_TASKFILE_PATH: Taskfile.yml
|
||||||
|
CONAN_BUILD_VERSION: latest
|
||||||
|
|
||||||
|
includes:
|
||||||
|
# Remote includes
|
||||||
|
conan2-config: "{{.CONAN2_CONFIG_URL}}/raw/branch/{{.CONAN2_CONFIG_BRANCH}}/{{.CONAN2_CONFIG_TASKFILE_PATH}}"
|
||||||
|
|
||||||
|
# Local modules
|
||||||
|
|
||||||
|
hesai: ./Taskfile.hesai.yml
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
default:
|
||||||
|
desc: Show available tasks
|
||||||
|
silent: true
|
||||||
|
cmds:
|
||||||
|
- task: version
|
||||||
|
- task --list
|
||||||
|
|
||||||
|
version:
|
||||||
|
desc: Display component version information
|
||||||
|
silent: true
|
||||||
|
vars:
|
||||||
|
NAME_COMPONENT: conan2-ros2-hesai-lidar
|
||||||
|
URL_COMPONENT: https://package-cloud.dns.army/ros2/conan2-ros2-hesai-lidar
|
||||||
|
GIT_SHA:
|
||||||
|
sh: git rev-parse --short HEAD
|
||||||
|
GIT_REF:
|
||||||
|
sh: git rev-parse --abbrev-ref HEAD
|
||||||
|
cmds:
|
||||||
|
- printf "{{.B_MAGENTA}}Component{{.RESET}} - {{.CYAN}}{{.NAME_COMPONENT}}{{.RESET}}\n"
|
||||||
|
- printf "{{.B_MAGENTA}}URL{{.RESET}} - {{.CYAN}}{{.URL_COMPONENT}}{{.RESET}}\n"
|
||||||
|
- printf "{{.B_MAGENTA}}Branch{{.RESET}} - {{.CYAN}}{{.GIT_REF}} {{.B_WHITE}}{{.RESET}} - {{.B_MAGENTA}}Hash{{.RESET}} - {{.GREEN}}{{.GIT_SHA}}{{.RESET}}\n"
|
||||||
|
|
||||||
|
install:gcc:
|
||||||
|
desc: Install default gcc g++ build-toolchain for ubuntu
|
||||||
|
cmds:
|
||||||
|
- apt-get install build-essential --no-install-recommends --yes
|
||||||
|
|
||||||
219
conanfile.py
Normal file
219
conanfile.py
Normal file
@@ -0,0 +1,219 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
from conan import ConanFile
|
||||||
|
from conan.tools.cmake import CMakeToolchain, CMakeDeps, cmake_layout
|
||||||
|
from conan.tools.files import copy, rmdir, patch
|
||||||
|
from conan.tools.scm import Git
|
||||||
|
from conan.errors import ConanInvalidConfiguration, ConanException
|
||||||
|
|
||||||
|
class HesaiLidarDriver(ConanFile):
|
||||||
|
name = "hesai-lidar-ros2-jazzy-driver"
|
||||||
|
description = "ROS2 (Jazzy) Driver for Hesai LiDAR sensor"
|
||||||
|
license = "BSD-3-Clause"
|
||||||
|
url = "https://github.com/HesaiTechnology/HesaiLidar_ROS_2.0"
|
||||||
|
author = "thommyho1988@gmail.com"
|
||||||
|
topics = ("ros2", "lidar", "hesai", "driver")
|
||||||
|
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
|
||||||
|
options = {
|
||||||
|
"with_cuda": [True, False],
|
||||||
|
}
|
||||||
|
default_options = {
|
||||||
|
"with_cuda": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def export_sources(self):
|
||||||
|
copy(self, "patches/**", self.recipe_folder, self.export_sources_folder)
|
||||||
|
copy(self, "LICENSE", self.recipe_folder, self.export_sources_folder)
|
||||||
|
copy(self, "README.md", self.recipe_folder, self.export_sources_folder)
|
||||||
|
|
||||||
|
def layout(self):
|
||||||
|
cmake_layout(self)
|
||||||
|
|
||||||
|
def build_requirements(self):
|
||||||
|
self.tool_requires("make/4.4.1")
|
||||||
|
self.tool_requires("cmake/3.31.9")
|
||||||
|
self.tool_requires("ros2-jazzy-toolchain/latest")
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
self.requires("ros2-jazzy-python/latest")
|
||||||
|
self.requires("ros2-jazzy-toolchain/latest")
|
||||||
|
self.requires("openssl/1.1.1w")
|
||||||
|
self.requires("yaml-cpp/0.8.0")
|
||||||
|
self.requires("tinyxml2/7.1.0")
|
||||||
|
self.requires("boost/1.74.0", options={
|
||||||
|
"without_thread": False,
|
||||||
|
"without_system": False,
|
||||||
|
"without_chrono": False,
|
||||||
|
})
|
||||||
|
|
||||||
|
def validate(self):
|
||||||
|
if self.options.with_cuda and self.settings.arch not in ["x86_64", "armv8"]:
|
||||||
|
raise ConanInvalidConfiguration("CUDA is only supported on x86_64 and armv8")
|
||||||
|
|
||||||
|
def source(self):
|
||||||
|
if self.version not in self.conan_data.get("sources", {}):
|
||||||
|
raise ConanInvalidConfiguration(f"Version '{self.version}' not found in conandata.yml")
|
||||||
|
|
||||||
|
data = self.conan_data["sources"][self.version]
|
||||||
|
tmp_src = "src_tmp"
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.output.info(f"Cloning {data['url']} into temporary directory...")
|
||||||
|
git = Git(self)
|
||||||
|
git.clone(url=data["url"], target=tmp_src, args=["--recursive"])
|
||||||
|
|
||||||
|
if "revision" in data:
|
||||||
|
self.output.info(f"Checking out revision {data['revision']}")
|
||||||
|
git_tmp = Git(self, folder=tmp_src)
|
||||||
|
git_tmp.checkout(commit=data["revision"])
|
||||||
|
git_tmp.run("submodule update --init --recursive")
|
||||||
|
|
||||||
|
self.output.info("Moving sources to recipe root...")
|
||||||
|
copy(self, "*", src=tmp_src, dst=".")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
raise ConanException(f"Source retrieval failed: {e}")
|
||||||
|
finally:
|
||||||
|
if os.path.exists(tmp_src):
|
||||||
|
rmdir(self, tmp_src)
|
||||||
|
|
||||||
|
patch_dir = os.path.join(self.source_folder, "patches", self.version)
|
||||||
|
if os.path.exists(patch_dir):
|
||||||
|
patches = sorted([p for p in os.listdir(patch_dir) if p.endswith(".patch")])
|
||||||
|
for p in patches:
|
||||||
|
self.output.info(f"Applying patch: {p}")
|
||||||
|
patch(self, patch_file=os.path.join(patch_dir, p))
|
||||||
|
|
||||||
|
def _get_numpy_include(self, python_exe):
|
||||||
|
try:
|
||||||
|
cmd = [python_exe, "-c", "import numpy; print(numpy.get_include())"]
|
||||||
|
return subprocess.check_output(cmd, text=True).strip()
|
||||||
|
except (subprocess.CalledProcessError, FileNotFoundError, OSError) as e:
|
||||||
|
self.output.warning(f"Failed to determine NumPy include path: {e}")
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def generate(self):
|
||||||
|
deps = CMakeDeps(self)
|
||||||
|
deps.generate()
|
||||||
|
|
||||||
|
tc = CMakeToolchain(self)
|
||||||
|
python_dep = self.dependencies["ros2-jazzy-python"]
|
||||||
|
python_exe = python_dep.conf_info.get("user.ros2:python_interpreter", check_type=str)
|
||||||
|
|
||||||
|
if python_exe:
|
||||||
|
numpy_include = self._get_numpy_include(python_exe)
|
||||||
|
tc.variables["Python3_EXECUTABLE"] = python_exe
|
||||||
|
tc.variables["Python_EXECUTABLE"] = python_exe
|
||||||
|
if numpy_include:
|
||||||
|
tc.variables["Python3_NumPy_INCLUDE_DIR"] = numpy_include
|
||||||
|
|
||||||
|
self._configure_special_flags(tc, python_dep)
|
||||||
|
tc.generate()
|
||||||
|
|
||||||
|
def _configure_special_flags(self, tc, python_dep):
|
||||||
|
cross_blob = False
|
||||||
|
if "cross_blob" in python_dep.options:
|
||||||
|
cross_blob = bool(python_dep.options.cross_blob)
|
||||||
|
|
||||||
|
if self.options.with_cuda:
|
||||||
|
if cross_blob:
|
||||||
|
raise ConanInvalidConfiguration("CUDA not available as conan package due to NVIDIA license.")
|
||||||
|
self.output.info("Enabling CUDA Support")
|
||||||
|
tc.variables["FIND_CUDA"] = "ON"
|
||||||
|
|
||||||
|
if cross_blob:
|
||||||
|
self.output.info("Enabling Cross-Blob workarounds (No LTO)")
|
||||||
|
tc.variables["CMAKE_INTERPROCEDURAL_OPTIMIZATION"] = "OFF"
|
||||||
|
tc.cache_variables["CMAKE_C_FLAGS"] = "-fno-lto"
|
||||||
|
tc.cache_variables["CMAKE_CXX_FLAGS"] = "-fno-lto"
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
# 1. Resolve Setup Script
|
||||||
|
build_dep = self.dependencies.get("ros2-jazzy-toolchain")
|
||||||
|
setup_script = None
|
||||||
|
|
||||||
|
if build_dep:
|
||||||
|
env_vars = build_dep.buildenv_info.vars(self)
|
||||||
|
raw_cmd = env_vars.get("CONAN_ROS2_SOURCE_CMD", "")
|
||||||
|
if "source " in raw_cmd:
|
||||||
|
setup_script = raw_cmd.split("source ")[1].strip().split(" ")[0]
|
||||||
|
elif raw_cmd.strip().endswith((".sh", ".bash")):
|
||||||
|
setup_script = raw_cmd.strip()
|
||||||
|
|
||||||
|
# 2. Paths
|
||||||
|
tc_file = os.path.join(self.generators_folder, "conan_toolchain.cmake")
|
||||||
|
abs_build_base = os.path.join(self.build_folder, "colcon_build")
|
||||||
|
abs_install_base = os.path.join(self.build_folder, "install")
|
||||||
|
|
||||||
|
# 3. Colcon Command
|
||||||
|
colcon_cmd = (
|
||||||
|
f"colcon build --merge-install "
|
||||||
|
f"--build-base '{abs_build_base}' "
|
||||||
|
f"--install-base '{abs_install_base}' "
|
||||||
|
f"--event-handlers console_direct+ "
|
||||||
|
f"--cmake-args -DCMAKE_TOOLCHAIN_FILE='{tc_file}' "
|
||||||
|
f"-DCMAKE_BUILD_TYPE={self.settings.build_type}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 4. Execute (Bash wrapper for 'source')
|
||||||
|
if setup_script:
|
||||||
|
full_cmd = f'/bin/bash -c "source {setup_script} && {colcon_cmd}"'
|
||||||
|
else:
|
||||||
|
full_cmd = colcon_cmd
|
||||||
|
|
||||||
|
self.output.info(f"Building with: {full_cmd}")
|
||||||
|
self.run(full_cmd, shell=True, cwd=self.source_folder)
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
install_dir = os.path.join(self.build_folder, "install")
|
||||||
|
if not os.path.exists(install_dir):
|
||||||
|
raise ConanException(f"Build failed to produce install directory: {install_dir}")
|
||||||
|
|
||||||
|
# 1. Define Subdirectory
|
||||||
|
ros_package_dir = os.path.join(self.package_folder, "hesai_ros_driver")
|
||||||
|
|
||||||
|
# 2. Copy ROS Artifacts to Subdirectory
|
||||||
|
copy(self, "*", src=install_dir, dst=ros_package_dir)
|
||||||
|
|
||||||
|
# 3. Copy Metadata to Root
|
||||||
|
copy(self, "LICENSE", src=self.source_folder, dst=self.package_folder)
|
||||||
|
copy(self, "README.md", src=self.source_folder, dst=self.package_folder)
|
||||||
|
|
||||||
|
# 4. Cleanup
|
||||||
|
rmdir(self, os.path.join(ros_package_dir, "share", "doc"))
|
||||||
|
rmdir(self, os.path.join(ros_package_dir, "colcon_build"))
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
# 1. Define the ROS Root inside the package
|
||||||
|
ros_root = os.path.join(self.package_folder, "hesai_ros_driver")
|
||||||
|
|
||||||
|
# 2. Cpp Info (Relative to package_folder)
|
||||||
|
self.cpp_info.libs = ["hesai_ros_driver"]
|
||||||
|
self.cpp_info.libdirs = [os.path.join("hesai_ros_driver", "lib")]
|
||||||
|
self.cpp_info.includedirs = [os.path.join("hesai_ros_driver", "include")]
|
||||||
|
self.cpp_info.bindirs = [os.path.join("hesai_ros_driver", "bin")]
|
||||||
|
|
||||||
|
# 3. Environment Variables (Absolute Paths)
|
||||||
|
# Critical: These ensure ROS 2 finds the package in the subdirectory
|
||||||
|
self.runenv_info.prepend_path("AMENT_PREFIX_PATH", ros_root)
|
||||||
|
self.buildenv_info.prepend_path("AMENT_PREFIX_PATH", ros_root)
|
||||||
|
|
||||||
|
self.runenv_info.prepend_path("CMAKE_PREFIX_PATH", ros_root)
|
||||||
|
self.buildenv_info.prepend_path("CMAKE_PREFIX_PATH", ros_root)
|
||||||
|
|
||||||
|
self.runenv_info.prepend_path("PATH", os.path.join(ros_root, "bin"))
|
||||||
|
self.runenv_info.prepend_path("LD_LIBRARY_PATH", os.path.join(ros_root, "lib"))
|
||||||
|
|
||||||
|
# 4. Python Path Calculation
|
||||||
|
lib_dir = os.path.join(ros_root, "lib")
|
||||||
|
if os.path.exists(lib_dir):
|
||||||
|
for item in os.listdir(lib_dir):
|
||||||
|
if item.startswith("python"):
|
||||||
|
site_packages = os.path.join(lib_dir, item, "site-packages")
|
||||||
|
if os.path.exists(site_packages):
|
||||||
|
self.runenv_info.prepend_path("PYTHONPATH", site_packages)
|
||||||
|
self.buildenv_info.prepend_path("PYTHONPATH", site_packages)
|
||||||
|
break
|
||||||
Reference in New Issue
Block a user