Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,37 @@ jobs:
- uses: DeterminateSystems/nix-installer-action@main
- uses: DeterminateSystems/magic-nix-cache-action@main

# The dev shell pins eigen_5. Ubuntu ships 3.4.0 through at least 26.04
# LTS, which lacks Matrix::canonicalEulerAngles() -- so this cannot be an
# apt-based job without patching the source.
- name: Build all targets
run: |
nix develop --command bash -c '
cmake -B build .
make -C build -j"$(nproc)" vision_processor geometry_benchmark blob_benchmark
'

build-apt:
name: Build (Ubuntu 24.04, apt)
# Pinned, not ubuntu-latest: 24.04 is the release target, and its packages
# (protobuf 3.21, OpenCV 4.6, ffmpeg 6.1) are far older than nixpkgs'.
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

# setup.sh's Debian package list, minus its runtime-only and Python
# packages. Keep the two in sync.
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends build-essential cmake pkg-config libyaml-cpp-dev \
ocl-icd-opencl-dev libeigen3-dev libopencv-dev protobuf-compiler libprotobuf-dev \
libavcodec-dev libavformat-dev libavutil-dev libdc1394-dev

- name: Build all targets
run: |
cmake -B build .
make -C build -j"$(nproc)" vision_processor geometry_benchmark blob_benchmark

python:
name: Python (wrapper_backend)
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .gitlab-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ build:
stage: build
script:
- apt -qq update
- DEBIAN_FRONTEND=noninteractive apt -y install --no-install-recommends build-essential cmake pkg-config libyaml-cpp-dev ocl-icd-opencl-dev libeigen3-dev libopencv-dev protobuf-compiler libprotobuf-dev ffmpeg libavcodec-dev libavformat-dev libavutil-dev > /dev/null
- DEBIAN_FRONTEND=noninteractive apt -y install --no-install-recommends build-essential cmake pkg-config libyaml-cpp-dev ocl-icd-opencl-dev libeigen3-dev libopencv-dev protobuf-compiler libprotobuf-dev ffmpeg libavcodec-dev libavformat-dev libavutil-dev libdc1394-dev > /dev/null
- cmake -B build .
- make -C build -j vision_processor
68 changes: 55 additions & 13 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,36 @@
# limitations under the License.

cmake_minimum_required(VERSION 3.22)

# A build directory belongs to one toolchain: nix develop or the distro's
# packages. CMake caches the first one's compiler and library paths and would
# otherwise silently mix them with the other's; a build from the other one
# makes a binary that only runs in the first.
option(TOOLCHAIN_CHECK "Stop when a build directory is used from the toolchain that didn't configure it" ON)
if(TOOLCHAIN_CHECK AND DEFINED CACHE{CMAKE_CXX_COMPILER})
set(TOOLCHAIN_COMPILER "$CACHE{CMAKE_CXX_COMPILER}")
set(TOOLCHAIN_BUILD_DIR "${CMAKE_BINARY_DIR}")
include("${CMAKE_SOURCE_DIR}/cmake/CheckToolchain.cmake")
endif()

project(vision_processor)
enable_language(ASM)

option(WITH_SPINNAKER "Build with Spinnaker support (if library available)" ON)
option(WITH_MVIMPACT "Build with mvIMPACT/Bluefox support (if library available)" ON)
option(WITH_DC1394 "Build with DC1394 (IIDC FireWire) support (if library available)" ON)
option(NATIVE_ARCH "Optimize Release builds for this machine's CPU (-march=native); the binary may not run on others" ON)

# Adapted from https://stackoverflow.com/a/48832234 CC BY-SA 4.0 by einpoklum
if (NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "" FORCE)
endif()

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native -ftree-vectorize -ffast-math")
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -ffast-math")
if(NATIVE_ARCH)
string(APPEND CMAKE_CXX_FLAGS_RELEASE " -march=native")
endif()
add_compile_options("-Wall")
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

Expand Down Expand Up @@ -61,8 +77,21 @@ include_directories(SYSTEM ${YAML_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${SPINNAK

include_directories(src)

set(PROTOC_OUT_DIR "${CMAKE_SOURCE_DIR}/src/proto")
include_directories("${PROTOC_OUT_DIR}")
# Generated code lives in the build directory, so each build directory (one per
# toolchain) has its own: protoc's output only compiles against the protobuf
# headers of the protoc that wrote it.
set(GENERATED_DIR "${CMAKE_BINARY_DIR}/generated")
set(PROTOC_OUT_DIR "${GENERATED_DIR}/proto")
include_directories("${GENERATED_DIR}" "${PROTOC_OUT_DIR}")

# Older checkouts generated into src/, where a quoted #include from src/ would
# find these before the build directory's copies. They're gitignored output.
foreach(stale "src/proto" "src/cl_kernels.h" "src/cl_kernels.S")
if(EXISTS "${CMAKE_SOURCE_DIR}/${stale}")
file(REMOVE_RECURSE "${CMAKE_SOURCE_DIR}/${stale}")
message(STATUS "Removed generated ${stale}, now generated in ${GENERATED_DIR}")
endif()
endforeach()

# league proto repository provides a generator function that fixes OUT_DIR limitations with protoc provided function
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/proto/cmake")
Expand Down Expand Up @@ -104,25 +133,37 @@ foreach(input_file IN LISTS CL_KERNELS)
endforeach()

# Don't override cl_kernels.h or cl_kernels.S if already up-to-date to prevent unnecessary recompilation
if(EXISTS "${CMAKE_SOURCE_DIR}/src/cl_kernels.h")
file(READ "${CMAKE_SOURCE_DIR}/src/cl_kernels.h" CL_KERNEL_HEADER_OLD)
set(CL_KERNEL_H "${GENERATED_DIR}/cl_kernels.h")
set(CL_KERNEL_S "${GENERATED_DIR}/cl_kernels.S")

if(EXISTS "${CL_KERNEL_H}")
file(READ "${CL_KERNEL_H}" CL_KERNEL_HEADER_OLD)
endif()
if(NOT "${CL_KERNEL_HEADER_OLD}" STREQUAL "${CL_KERNEL_HEADER}")
file(WRITE "${CMAKE_SOURCE_DIR}/src/cl_kernels.h" "${CL_KERNEL_HEADER}")
file(WRITE "${CL_KERNEL_H}" "${CL_KERNEL_HEADER}")
message(STATUS "(Re-)Generated cl_kernels.h")
endif()

if(EXISTS "src/cl_kernels.S")
file(READ "src/cl_kernels.S" CL_KERNEL_ASM_OLD)
if(EXISTS "${CL_KERNEL_S}")
file(READ "${CL_KERNEL_S}" CL_KERNEL_ASM_OLD)
endif()
if(NOT "${CL_KERNEL_ASM_OLD}" STREQUAL "${CL_KERNEL_ASM}")
file(WRITE "src/cl_kernels.S" "${CL_KERNEL_ASM}")
file(WRITE "${CL_KERNEL_S}" "${CL_KERNEL_ASM}")
message(STATUS "(Re-)Generated cl_kernels.S")
endif()

add_custom_target(AUTOGENERATE DEPENDS "src/cl_kernels.S" ${PROTO_SRCS} ${PROTO_HDRS})
set_property(SOURCE "src/cl_kernels.S" APPEND PROPERTY OBJECT_DEPENDS ${CL_KERNEL_PATHS})
list(APPEND SRC ${PROTO_SRCS} "src/cl_kernels.S")
add_custom_target(AUTOGENERATE DEPENDS "${CL_KERNEL_S}" ${PROTO_SRCS} ${PROTO_HDRS})

# No outputs, so it runs on every build, before anything is generated or compiled.
if(TOOLCHAIN_CHECK)
add_custom_target(CHECK_TOOLCHAIN
COMMAND ${CMAKE_COMMAND} "-DTOOLCHAIN_COMPILER=${CMAKE_CXX_COMPILER}" "-DTOOLCHAIN_BUILD_DIR=${CMAKE_BINARY_DIR}"
-P "${CMAKE_SOURCE_DIR}/cmake/CheckToolchain.cmake"
VERBATIM)
add_dependencies(AUTOGENERATE CHECK_TOOLCHAIN)
endif()
set_property(SOURCE "${CL_KERNEL_S}" APPEND PROPERTY OBJECT_DEPENDS ${CL_KERNEL_PATHS})
list(APPEND SRC ${PROTO_SRCS} "${CL_KERNEL_S}")

add_executable(${PROJECT_NAME} ${SRC} "src/main.cpp")
add_executable("geometry_benchmark" ${SRC} "src/geometry_benchmark.cpp")
Expand All @@ -137,4 +178,5 @@ if (SPINNAKER_LIBS)
add_executable("spinnaker_probe" "tools/spinnaker_probe.cpp")
endif ()

install(TARGETS ${PROJECT_NAME} DESTINATION /usr/local/bin)
include(GNUInstallDirs)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,17 @@ Installation with PIP: `pip install protobuf pyyaml`
- OpenCV
- protobuf
- yaml-cpp
- libdc1394 (optional, for FireWire cameras)

3. Compile vision_processor:

git submodule update --init --recursive
cmake -B build .
make -C build vision_processor

The same works inside `nix develop` (see `flake.nix`). A build directory belongs to the toolchain that configured
it: to switch between nix and the distro packages, delete `build` first, or CMake stops with an error.


## Setup

Expand Down
16 changes: 16 additions & 0 deletions cmake/CheckToolchain.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Stops a build directory being used from the toolchain that didn't configure
# it: nix develop's or the distro's packages. CMakeLists.txt includes this when
# reconfiguring, and runs it with cmake -P before every build.
#
# Expects TOOLCHAIN_COMPILER (the build directory's C++ compiler) and
# TOOLCHAIN_BUILD_DIR.

string(FIND "${TOOLCHAIN_COMPILER}" "/nix/store/" _toolchain_nix_compiler)

if(DEFINED ENV{IN_NIX_SHELL} AND _toolchain_nix_compiler EQUAL -1)
message(FATAL_ERROR "You're in nix develop, but ${TOOLCHAIN_BUILD_DIR} was configured outside it. "
"Leave nix develop to build it, or delete it and configure it again here.")
elseif(NOT DEFINED ENV{IN_NIX_SHELL} AND NOT _toolchain_nix_compiler EQUAL -1)
message(FATAL_ERROR "You're not in nix develop, but ${TOOLCHAIN_BUILD_DIR} was configured inside it. "
"Enter nix develop to build it, or delete it and configure it again here.")
endif()
4 changes: 2 additions & 2 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ fi
# Determine distribution/package manager
if [[ -f /etc/arch-release ]]; then
echo -e "\e[92m » Arch based distribution\e[39m"
packages="gcc make cmake pkgconf eigen opencv yaml-cpp opencl-clhpp python-protobuf python-yaml $opencl_arch"
packages="gcc make cmake pkgconf eigen opencv yaml-cpp opencl-clhpp libdc1394 python-protobuf python-yaml $opencl_arch"
check_cmd="pacman -Qi $packages"
install_cmd="sudo pacman -S $packages"
elif [[ -f /etc/debian_version ]]; then
echo -e "\e[92m » Debian based distribution\e[39m"
packages="build-essential cmake pkg-config libyaml-cpp-dev ocl-icd-opencl-dev libeigen3-dev libopencv-dev protobuf-compiler libprotobuf-dev ffmpeg libavcodec-dev libavformat-dev libavutil-dev python3-protobuf python3-yaml $opencl_debian"
packages="build-essential cmake pkg-config libyaml-cpp-dev ocl-icd-opencl-dev libeigen3-dev libopencv-dev protobuf-compiler libprotobuf-dev ffmpeg libavcodec-dev libavformat-dev libavutil-dev libdc1394-dev python3-protobuf python3-yaml $opencl_debian"
check_cmd="dpkg -s $packages"
install_cmd="sudo apt install --no-install-recommends $packages"
else
Expand Down
Loading