From a9b4e4e7dbefd5fe2de6cbf5573bfbfb2ca6aab5 Mon Sep 17 00:00:00 2001 From: oleg Date: Sun, 12 Apr 2026 19:01:22 +0300 Subject: [PATCH] add docker run, arm64 cross-build in docker --- CMakeLists.txt | 126 +++----------------------------- Makefile | 124 +++++++++++++++++++++++++++++++ README.md | 93 ++++++++++++----------- cmake/dependencies.cmake | 114 +++++++++++++++++++++++++++++ cmake/toolchain-aarch64.cmake | 27 +++++++ Dockerfile => docker/Dockerfile | 2 - docker/Dockerfile.cross | 13 ++++ docker/Dockerfile.dev | 17 +++++ docker/Dockerfile.sysroot | 15 ++++ src/canid_unit.cpp | 10 --- src/mainform.cpp | 4 - src/recorder.cpp | 25 ++----- src/recorder.hpp | 2 - 13 files changed, 380 insertions(+), 192 deletions(-) create mode 100644 Makefile create mode 100644 cmake/dependencies.cmake create mode 100644 cmake/toolchain-aarch64.cmake rename Dockerfile => docker/Dockerfile (89%) create mode 100644 docker/Dockerfile.cross create mode 100644 docker/Dockerfile.dev create mode 100644 docker/Dockerfile.sysroot diff --git a/CMakeLists.txt b/CMakeLists.txt index d246c6b..e1953f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,127 +2,21 @@ cmake_minimum_required(VERSION 3.13) set(CMAKE_POLICY_VERSION_MINIMUM 3.5) set(CMAKE_CXX_STANDARD 23) -set(CMAKE_BUILD_TYPE Debug) +set(CMAKE_BUILD_TYPE Release) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_MESSAGE_LOG_LEVEL TRACE) set(CMAKE_VERBOSE_MAKEFILE OFF) -set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE INTERNAL "cxx compiler") + +if(NOT CMAKE_TOOLCHAIN_FILE) + set(CMAKE_CXX_COMPILER /usr/bin/clang++) +endif() + option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) - -include(FetchContent) -set(FETCHCONTENT_QUIET FALSE) - -FetchContent_Declare( - tpl - GIT_REPOSITORY https://gitlab.com/eidheim/tiny-process-library.git - GIT_TAG 8bbb5a211c5c9df8ee69301da9d22fb977b27dc1 - GIT_PROGRESS TRUE -) - -FetchContent_MakeAvailable(tpl) -FetchContent_Declare( - ftxui - GIT_REPOSITORY https://github.com/ArthurSonzogni/FTXUI.git - GIT_TAG v6.0.0 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE - PATCH_COMMAND git apply --check ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-empty-container.patch 2>/dev/null && git apply ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-empty-container.patch || true COMMAND git apply --check ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-window.patch 2>/dev/null && git apply ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-window.patch || true -) - -FetchContent_MakeAvailable(ftxui) -FetchContent_Declare( - sqlite_modern - GIT_REPOSITORY https://github.com/SqliteModernCpp/sqlite_modern_cpp - GIT_TAG 6e3009973025e0016d5573529067714201338c80 - GIT_PROGRESS TRUE -) - -FetchContent_GetProperties(sqlite_modern) -if(NOT sqlite_modern_POPULATED) - FetchContent_Populate(sqlite_modern) -endif() - - -option(STATIC "Set to ON to build xlnt as a static library instead of a shared library" OFF) -FetchContent_Declare( - xlnt - GIT_REPOSITORY https://github.com/xlnt-community/xlnt.git - GIT_TAG e165887739147027e7fbab918280b88f9efa5ffb - GIT_PROGRESS TRUE -) - -FetchContent_MakeAvailable(xlnt) - -# Suppress warnings in xlnt -if(TARGET xlnt) - target_compile_options(xlnt PRIVATE - -Wno-unsafe-buffer-usage-in-libc-call - -Wno-unsafe-buffer-usage - -Wno-undefined-reinterpret-cast - -Wno-extra-semi-stmt - -Wno-sign-conversion - -Wno-old-style-cast - -Wno-switch-default - -Wno-nrvo - -Wno-reserved-identifier - -Wno-unused-but-set-variable - -Wno-missing-prototypes - -Wno-character-conversion - -Wno-implicit-int-float-conversion - -Wno-float-equal - -Wno-global-constructors - -Wno-unique-object-duplication - ) -endif() - -set(FMT_TEST OFF CACHE BOOL "" FORCE) -set(FMT_DOC OFF CACHE BOOL "" FORCE) -FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt - GIT_TAG 11.1.4 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE -) - -FetchContent_MakeAvailable(fmt) -set(JSON_BuildTests OFF CACHE BOOL "" FORCE) -set(JSON_Install OFF CACHE BOOL "" FORCE) -FetchContent_Declare( - json - GIT_REPOSITORY https://github.com/nlohmann/json - GIT_TAG v3.12.0 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE -) - -FetchContent_MakeAvailable(json) -set(SPDLOG_FMT_EXTERNAL OFF CACHE BOOL "" FORCE) -FetchContent_Declare( - spdlog - GIT_REPOSITORY https://github.com/gabime/spdlog - GIT_TAG v1.15.3 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE -) - -FetchContent_MakeAvailable(spdlog) - -FetchContent_Declare( - clipp - GIT_REPOSITORY https://github.com/muellan/clipp.git - GIT_TAG v1.2.3 - GIT_SHALLOW TRUE - GIT_PROGRESS TRUE -) - -FetchContent_GetProperties(clipp) -if(NOT clipp_POPULATED) - FetchContent_Populate(clipp) -endif() +include(cmake/dependencies.cmake) project(canscope) file(GLOB_RECURSE SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp) + add_executable(${CMAKE_PROJECT_NAME} ${SOURCES}) target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} @@ -136,5 +30,5 @@ target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ${clipp_SOURCE_DIR}/include ) -target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ftxui::component ftxui::screen ftxui::dom tiny-process-library xlnt sqlite3 spdlog::spdlog systemd z ${Boost_LIBRARIES}) -# target_link_libraries(${CMAKE_PROJECT_NAME} PUBLIC sqlite3 ${Boost_LIBRARIES}) +target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE ftxui::component ftxui::screen ftxui::dom tiny-process-library xlnt sqlite3_lib z ${Boost_LIBRARIES}) + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..58a7fa6 --- /dev/null +++ b/Makefile @@ -0,0 +1,124 @@ +BUILD_DIR := build/native +BUILD_STATIC := build/native_static +BUILD_ARM64 := build/arm64 +BUILD_ARM64_ST := build/arm64_static +JOBS := $(shell nproc) + +PREFIX ?= /usr/local +INSTALL_DIR := $(DESTDIR)$(PREFIX)/canscope + +DEV_IMAGE := canscope-dev +BUILD_DOCKER := build/docker +CROSS_IMAGE := canscope-cross +SYSROOT_IMAGE := canscope-sysroot +SYSROOT_CONTAINER := canscope-sysroot +DOCKER_SYSROOT := /sysroot +TOOLCHAIN := cmake/toolchain-aarch64.cmake +SSH_DIR ?= $(HOME)/.ssh +CMAKE_COMMON := -DFETCHCONTENT_UPDATES_DISCONNECTED=ON -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + +SSH_PREP := set -euo pipefail; \ + rm -rf /root/.ssh; \ + mkdir -p /root/.ssh; \ + cp -r /host_ssh/. /root/.ssh/; \ + chown -R $$(id -u):$$(id -g) /root/.ssh; \ + chmod 700 /root/.ssh; \ + find /root/.ssh -type f -exec chmod 600 {} \;; \ + [ -f /root/.ssh/known_hosts ] && chmod 644 /root/.ssh/known_hosts || true; \ + chmod 644 /root/.ssh/*.pub || true; \ + KEY=$$(find /root/.ssh -maxdepth 1 -type f \ + ! -name "*.pub" \ + ! -name "known_hosts" \ + ! -name "authorized_keys" \ + ! -name "config" | head -n1); \ + if [ -z "$$KEY" ]; then \ + echo "No SSH private key found in ~/.ssh"; \ + exit 1; \ + fi; \ + export GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new -i $$KEY"; + +.PHONY: build build_static install install_static docker-run \ + build_arm64 build_arm64_static clean list + +HOST_OS := $(shell uname -s) +HOST_ARCH := $(shell uname -m) + +build: ## Build $(HOST_ARCH) (dynamic linking) + cmake -G Ninja -B $(BUILD_DIR) -S . $(CMAKE_COMMON) \ + -DBUILD_SHARED_LIBS=ON \ + -DCMAKE_INSTALL_RPATH='$$ORIGIN/../canscope/lib' + cmake --build $(BUILD_DIR) + +build_static: ## Build $(HOST_ARCH) (static linking) + cmake -G Ninja -B $(BUILD_STATIC) -S . $(CMAKE_COMMON) \ + -DCMAKE_EXE_LINKER_FLAGS="-static" \ + -DBUILD_SHARED_LIBS=OFF \ + -DSTATIC=ON + cmake --build $(BUILD_STATIC) + +install: ## Install binary to PREFIX/bin, shared libs to PREFIX/canscope/lib + @test -f $(BUILD_DIR)/canscope || { echo "Error: run 'make build' first"; exit 1; } + install -d $(DESTDIR)$(PREFIX)/bin $(INSTALL_DIR)/lib + install -m 755 $(BUILD_DIR)/canscope $(DESTDIR)$(PREFIX)/bin/ + patchelf --set-rpath '$$ORIGIN/../canscope/lib' $(DESTDIR)$(PREFIX)/bin/canscope + find $(BUILD_DIR)/_deps -name '*.so*' -type f -exec install -m 755 {} $(INSTALL_DIR)/lib/ \; + find $(BUILD_DIR)/_deps -name '*.so*' -type l -exec cp -a {} $(INSTALL_DIR)/lib/ \; + +install_static: ## Install static binary to PREFIX/bin + @test -f $(BUILD_STATIC)/canscope || { echo "Error: run 'make build_static' first"; exit 1; } + install -d $(DESTDIR)$(PREFIX)/bin + install -m 755 $(BUILD_STATIC)/canscope $(DESTDIR)$(PREFIX)/bin/ + +docker-run: ## Build and run in Docker (works on Linux/Mac/Windows) + docker build -t $(DEV_IMAGE) -f docker/Dockerfile.dev . + docker run --rm -it \ + -v $(CURDIR):/app \ + -v $(SSH_DIR):/host_ssh:ro \ + -v /etc/hosts:/etc/hosts:ro \ + $(DEV_IMAGE) \ + bash -c '$(SSH_PREP) cmake -G Ninja -B $(BUILD_DOCKER) -S . $(CMAKE_COMMON) \ + && cmake --build $(BUILD_DOCKER) \ + && ./$(BUILD_DOCKER)/canscope $(ARGS)' + +build_arm64: ## Cross-compile for arm64 (dynamic linking, in Docker) + docker build -t $(CROSS_IMAGE) -f docker/Dockerfile.cross . + docker build --platform=linux/arm64 -t $(SYSROOT_IMAGE) -f docker/Dockerfile.sysroot . + -docker rm -f $(SYSROOT_CONTAINER) 2>/dev/null + docker create --name $(SYSROOT_CONTAINER) $(SYSROOT_IMAGE) + docker run --rm \ + -v $(CURDIR):/app \ + -v $(SSH_DIR):/host_ssh:ro \ + --volumes-from $(SYSROOT_CONTAINER) \ + $(CROSS_IMAGE) \ + bash -c '$(SSH_PREP) cmake -G Ninja -B $(BUILD_ARM64) -S . $(CMAKE_COMMON) \ + -DCMAKE_TOOLCHAIN_FILE=/app/$(TOOLCHAIN) \ + -DSYSROOT=$(DOCKER_SYSROOT) \ + && cmake --build $(BUILD_ARM64)' + +build_arm64_static: ## Cross-compile for arm64 (static linking, in Docker) + docker build -t $(CROSS_IMAGE) -f docker/Dockerfile.cross . + docker build --platform=linux/arm64 -t $(SYSROOT_IMAGE) -f docker/Dockerfile.sysroot . + -docker rm -f $(SYSROOT_CONTAINER) 2>/dev/null + docker create --name $(SYSROOT_CONTAINER) $(SYSROOT_IMAGE) + docker run --rm \ + -v $(CURDIR):/app \ + -v $(SSH_DIR):/host_ssh:ro \ + --volumes-from $(SYSROOT_CONTAINER) \ + $(CROSS_IMAGE) \ + bash -c '$(SSH_PREP) cmake -G Ninja -B $(BUILD_ARM64_ST) -S . $(CMAKE_COMMON) \ + -DCMAKE_TOOLCHAIN_FILE=/app/$(TOOLCHAIN) \ + -DSYSROOT=$(DOCKER_SYSROOT) \ + -DCMAKE_EXE_LINKER_FLAGS=-static \ + -DBUILD_SHARED_LIBS=OFF \ + -DSTATIC=ON \ + && cmake --build $(BUILD_ARM64_ST)' + +clean: ## Remove all build directories + rm -rf build + +## Gets comments line and parses the name of target +list: ## Show available targets + @grep -E '^[a-zA-Z0-9_-]+:.*##' $(MAKEFILE_LIST) | \ + sed 's/:.* ## /\t/' | sed 's/:.*##/\t/' | \ + sed 's/$$(HOST_ARCH)/$(HOST_ARCH)/g' | \ + awk -F '\t' '{printf " \033[36m%-20s\033[0m %s\n", $$1, $$2}' diff --git a/README.md b/README.md index f10fe07..127823f 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,10 @@ CAN bus sniffer and SAE J1939 protocol analyzer. Reads CAN frames in `candump` f **Requirements:** - clang++ with C++23 support - CMake >= 3.13 -- System libraries: boost (signals2, spirit, phoenix), sqlite3, systemd, zlib +- Ninja +- System libraries: boost (signals2, spirit, phoenix), sqlite3, zlib -The rest of the dependencies are fetched automatically via CMake FetchContent: +Dependencies fetched automatically via CMake FetchContent: - [FTXUI](https://github.com/ArthurSonzogni/FTXUI) - terminal UI framework - [tiny-process-library](https://gitlab.com/eidheim/tiny-process-library) - subprocess management @@ -29,64 +30,76 @@ The rest of the dependencies are fetched automatically via CMake FetchContent: - [xlnt](https://github.com/xlnt-community/xlnt) - xlsx reading - [fmt](https://github.com/fmtlib/fmt) - text formatting - [nlohmann/json](https://github.com/nlohmann/json) - JSON library -- [spdlog](https://github.com/gabime/spdlog) - logging - [clipp](https://github.com/muellan/clipp) - CLI argument parsing -```bash -cmake -B build -S . && cmake --build build -j$(nproc) -``` - -Binary: `build/canscope` - -### Docker +### Available targets ```bash -docker build -t canscope . +make list # Show all targets + +make build # Native build (dynamic linking) +make build_static # Native build (static linking) +make install # Install to PREFIX (default /usr/local), requires patchelf +make install_static # Install static binary to PREFIX + +make docker-run ARGS='...' # Build and run in Docker (cross-platform) +make build_arm64 # Cross-compile for arm64 (dynamic) +make build_arm64_static # Cross-compile for arm64 (static) + +make clean # Remove all build artifacts ``` +### Native build + ```bash -# TUI mode -- requires terminal and CAN interface access -docker run -it --network=host canscope -e "candump can0" -j1939 /app/thirdparty/j1939da_2018.xlsx - -# Headless mode -docker run --network=host canscope -hl -e "candump can0" -j1939 /app/thirdparty/j1939da_2018.xlsx - -# Read from stdin -candump can0 | docker run -i canscope -j1939 /app/thirdparty/j1939da_2018.xlsx -hl +make build +./build/native/canscope -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx ``` +### Docker (cross-platform) + +Works on Linux, macOS (?), and Windows (?). Requires only Docker and Make. + +```bash +# TUI mode - local CAN interface +make docker-run ARGS='-e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx' + +# TUI mode - remote CAN interface via SSH (no data if will ask password - use public key access or sshpass utility) +make docker-run ARGS='-e "ssh user@remote candump can0" -j1939 thirdparty/j1939da_2018.xlsx' + +# Headless mode - create report about collected PGNs and SPNs +make docker-run ARGS='-hl -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx -of output.json' +``` + +### Cross-compile for arm64 + +```bash +make build_arm64 # dynamic linking +make build_arm64_static # static linking +``` + +Requires Docker. SSH keys from `~/.ssh` and `/etc/hosts` are forwarded into the build container for fetching private git dependencies. + ## Usage ```bash # TUI mode (default) -./build/canscope -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx +canscope -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx -# Headless -- JSON to stdout -./build/canscope -hl -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx +# Headless - JSON to stdout +canscope -hl -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx -# Headless -- JSON to file -./build/canscope -hl -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx -of output.json +# Headless - JSON to file +canscope -hl -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx -of output.json # Read from stdin (pipe) -candump can0 | ./build/canscope -j1939 thirdparty/j1939da_2018.xlsx - -# Headless with stdin -candump can0 | ./build/canscope -hl -j1939 thirdparty/j1939da_2018.xlsx - -# Docker -- TUI with CAN interface access -docker run -it --network=host canscope -e "candump can0" -j1939 /app/thirdparty/j1939da_2018.xlsx - -# Docker -- headless -docker run --network=host canscope -hl -e "candump can0" -j1939 /app/thirdparty/j1939da_2018.xlsx - -# Docker -- read from stdin -candump can0 | docker run -i canscope -hl -j1939 /app/thirdparty/j1939da_2018.xlsx +candump can0 | canscope -j1939 thirdparty/j1939da_2018.xlsx # Record to SQLite database -./build/canscope -rec -db recording.db -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx +canscope -rec -db recording.db -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx # Record + TUI -./build/canscope -rec -db recording.db -tui -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx +canscope -rec -db recording.db -tui -e "candump can0" -j1939 thirdparty/j1939da_2018.xlsx ``` > **Note:** J1939 decoding has only been tested with the Digital Annex 2018 edition. Other editions may work but are not guaranteed. @@ -106,7 +119,5 @@ candump can0 | docker run -i canscope -hl -j1939 /app/thirdparty/j1939da_2018.xl ## Roadmap -- **Cross-platform support** - Windows and macOS in addition to Linux -- **Docker deployment** - pre-built image for quick setup without manual compilation - **CANopen protocol support** - CANopen decoding alongside J1939 - **Other small features and enhancements** - UI improvements, performance optimizations, additional export formats diff --git a/cmake/dependencies.cmake b/cmake/dependencies.cmake new file mode 100644 index 0000000..1bc642d --- /dev/null +++ b/cmake/dependencies.cmake @@ -0,0 +1,114 @@ +include(FetchContent) +set(FETCHCONTENT_QUIET FALSE) + +FetchContent_Declare( + tpl + GIT_REPOSITORY git@gitlab.com:eidheim/tiny-process-library.git + GIT_TAG 8bbb5a211c5c9df8ee69301da9d22fb977b27dc1 + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(tpl) + +FetchContent_Declare( + ftxui + GIT_REPOSITORY git@github.com:ArthurSonzogni/FTXUI.git + GIT_TAG v6.0.0 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + PATCH_COMMAND git apply --check ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-empty-container.patch 2>/dev/null && git apply ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-empty-container.patch || true COMMAND git apply --check ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-window.patch 2>/dev/null && git apply ${CMAKE_SOURCE_DIR}/cmake/patches/ftxui-window.patch || true +) + +FetchContent_MakeAvailable(ftxui) + +FetchContent_Declare( + sqlite_modern + GIT_REPOSITORY git@github.com:SqliteModernCpp/sqlite_modern_cpp + GIT_TAG 6e3009973025e0016d5573529067714201338c80 + GIT_PROGRESS TRUE +) + +FetchContent_GetProperties(sqlite_modern) +if(NOT sqlite_modern_POPULATED) + FetchContent_Populate(sqlite_modern) +endif() + +FetchContent_Declare( + sqlite3 + URL https://www.sqlite.org/2024/sqlite-amalgamation-3470200.zip + DOWNLOAD_EXTRACT_TIMESTAMP TRUE +) + +FetchContent_MakeAvailable(sqlite3) +add_library(sqlite3_lib STATIC ${sqlite3_SOURCE_DIR}/sqlite3.c) +target_include_directories(sqlite3_lib PUBLIC ${sqlite3_SOURCE_DIR}) +target_compile_definitions(sqlite3_lib PRIVATE SQLITE_THREADSAFE=1 SQLITE_OMIT_LOAD_EXTENSION) + +option(STATIC "Set to ON to build xlnt as a static library instead of a shared library" OFF) +FetchContent_Declare( + xlnt + GIT_REPOSITORY git@github.com:xlnt-community/xlnt.git + GIT_TAG e165887739147027e7fbab918280b88f9efa5ffb + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(xlnt) + +# Suppress warnings in xlnt +if(TARGET xlnt) + target_compile_options(xlnt PRIVATE + -Wno-unsafe-buffer-usage-in-libc-call + -Wno-unsafe-buffer-usage + -Wno-undefined-reinterpret-cast + -Wno-extra-semi-stmt + -Wno-sign-conversion + -Wno-old-style-cast + -Wno-switch-default + -Wno-nrvo + -Wno-reserved-identifier + -Wno-unused-but-set-variable + -Wno-missing-prototypes + -Wno-character-conversion + -Wno-implicit-int-float-conversion + -Wno-float-equal + -Wno-global-constructors + -Wno-unique-object-duplication + ) +endif() + +set(FMT_TEST OFF CACHE BOOL "" FORCE) +set(FMT_DOC OFF CACHE BOOL "" FORCE) +FetchContent_Declare( + fmt + GIT_REPOSITORY git@github.com:fmtlib/fmt + GIT_TAG 11.1.4 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(fmt) + +set(JSON_BuildTests OFF CACHE BOOL "" FORCE) +set(JSON_Install OFF CACHE BOOL "" FORCE) +FetchContent_Declare( + json + GIT_REPOSITORY git@github.com:nlohmann/json + GIT_TAG v3.12.0 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) + +FetchContent_MakeAvailable(json) + +FetchContent_Declare( + clipp + GIT_REPOSITORY git@github.com:muellan/clipp.git + GIT_TAG v1.2.3 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE +) + +FetchContent_GetProperties(clipp) +if(NOT clipp_POPULATED) + FetchContent_Populate(clipp) +endif() diff --git a/cmake/toolchain-aarch64.cmake b/cmake/toolchain-aarch64.cmake new file mode 100644 index 0000000..f19300f --- /dev/null +++ b/cmake/toolchain-aarch64.cmake @@ -0,0 +1,27 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR aarch64) + +set(SYSROOT "/sysroot" CACHE PATH "Path to aarch64 sysroot") + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) + +set(CMAKE_C_COMPILER_TARGET aarch64-linux-gnu) +set(CMAKE_CXX_COMPILER_TARGET aarch64-linux-gnu) + +# Find GCC installation inside sysroot for crt files and libgcc +file(GLOB _gcc_dirs "${SYSROOT}/usr/lib/gcc/aarch64-*/*") +list(GET _gcc_dirs 0 _gcc_dir) +get_filename_component(GCC_INSTALL_DIR "${_gcc_dir}" DIRECTORY) + +set(CMAKE_C_FLAGS_INIT "--gcc-install-dir=${_gcc_dir}") +set(CMAKE_CXX_FLAGS_INIT "--gcc-install-dir=${_gcc_dir}") +set(CMAKE_LINKER_TYPE LLD) + +set(CMAKE_SYSROOT ${SYSROOT}) +set(CMAKE_FIND_ROOT_PATH ${SYSROOT}) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) diff --git a/Dockerfile b/docker/Dockerfile similarity index 89% rename from Dockerfile rename to docker/Dockerfile index 3a807e5..0ac1980 100644 --- a/Dockerfile +++ b/docker/Dockerfile @@ -7,8 +7,6 @@ RUN pacman -Syu --noconfirm && \ make \ git \ boost \ - sqlite \ - systemd-libs \ zlib && \ pacman -Scc --noconfirm diff --git a/docker/Dockerfile.cross b/docker/Dockerfile.cross new file mode 100644 index 0000000..8d76b02 --- /dev/null +++ b/docker/Dockerfile.cross @@ -0,0 +1,13 @@ +FROM manjarolinux/base:latest + +RUN pacman -Syu --noconfirm && \ + pacman -S --noconfirm \ + clang \ + lld \ + cmake \ + ninja \ + git \ + openssh \ + && pacman -Scc --noconfirm + +WORKDIR /app diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev new file mode 100644 index 0000000..68c68b1 --- /dev/null +++ b/docker/Dockerfile.dev @@ -0,0 +1,17 @@ +FROM manjarolinux/base:latest + +RUN pacman -Syu --noconfirm && \ + pacman -S --noconfirm \ + clang \ + lld \ + cmake \ + ninja \ + git \ + openssh \ + sshpass \ + boost \ + sqlite3 \ + zlib && \ + pacman -Scc --noconfirm + +WORKDIR /app diff --git a/docker/Dockerfile.sysroot b/docker/Dockerfile.sysroot new file mode 100644 index 0000000..303f25b --- /dev/null +++ b/docker/Dockerfile.sysroot @@ -0,0 +1,15 @@ +FROM --platform=linux/arm64 manjarolinux/base:latest + +RUN pacman -Syu --noconfirm && \ + pacman -S --noconfirm \ + boost \ + zlib \ + gcc && \ + pacman -Scc --noconfirm + +RUN mkdir -p /sysroot && \ + cp -a /usr /sysroot/usr && \ + cp -a /lib /sysroot/lib && \ + ([ -d /lib64 ] && cp -a /lib64 /sysroot/lib64 || true) + +VOLUME /sysroot diff --git a/src/canid_unit.cpp b/src/canid_unit.cpp index 0d34314..b2ca92a 100644 --- a/src/canid_unit.cpp +++ b/src/canid_unit.cpp @@ -11,8 +11,6 @@ #include "process.hpp" #include "tagsettings.hpp" #include "json/json.hpp" -#include -#include // For sqlite // #include "sqlite_modern_cpp.h" @@ -239,16 +237,8 @@ CanIDUnit::CanIDUnit(const std::string &iface, const std::string &canid, const s } bool CanIDUnit::OnEvent(ftxui::Event event) { - static auto log = spdlog::systemd_logger_mt("canidunit", "cansniffer-hover"); - log->set_level(spdlog::level::debug); - if (event.is_mouse()) { - bool prev = m_hovered_; m_hovered_ = m_box_.Contain(event.mouse().x, event.mouse().y); - if (m_hovered_ != prev) { - log->debug("{}: hover={} mouse=({},{}) box=({},{},{},{})", m_canid_, m_hovered_, event.mouse().x, event.mouse().y, - m_box_.x_min, m_box_.x_max, m_box_.y_min, m_box_.y_max); - } } return ftxui::ComponentBase::OnEvent(event); diff --git a/src/mainform.cpp b/src/mainform.cpp index 9e75856..d015824 100644 --- a/src/mainform.cpp +++ b/src/mainform.cpp @@ -10,8 +10,6 @@ #include #include #include -#include -#include #include #include @@ -24,8 +22,6 @@ ftxui::Component makeMainForm(ftxui::ScreenInteractive *screen, signals_map_t &s class Impl : public ftxui::ComponentBase { public: explicit Impl(ftxui::ScreenInteractive *screen, signals_map_t &smap) { - static auto logger = spdlog::systemd_logger_mt("mainform", "cansniffer"); - static bool canbus_params_export_dialog_shown = false, file_dialog_shown = false, canbus_player_dialog_shown = false, canplayer_is_ready = false; ; diff --git a/src/recorder.cpp b/src/recorder.cpp index eac82bf..ba97898 100644 --- a/src/recorder.cpp +++ b/src/recorder.cpp @@ -7,15 +7,9 @@ #define FMT_HEADER_ONLY #include -#include - Recorder::Recorder(const std::string &db_path, bool console_output) : disk_db_path_(db_path), console_output_(console_output) { - log_ = spdlog::systemd_logger_mt("recorder", "cansniffer-rec"); - log_->set_level(spdlog::level::info); - flush_task_ = std::async(std::launch::async, [this](std::stop_token st) { background_flush_task(st); }, flush_stop_.get_token()); - log_->info("recorder initialized, db_path={}", db_path); if (console_output_) fmt::println("Recording to: {}", db_path); } @@ -40,7 +34,6 @@ void Recorder::flushAndClose() { std::lock_guard lock(batch_mtx_); if (!pending_.empty()) { - log_->info("flushing remaining {} frames on exit", pending_.size()); compress_batch(); } } @@ -130,15 +123,14 @@ void Recorder::compress_batch() { disk_db << "INSERT INTO batches (ts_start, ts_end, frame_count, data) VALUES (?, ?, ?, ?);" << ts_start << ts_end << static_cast(pending_.size()) << compressed; - auto msg = fmt::format("Flushed batch: {} frames, {:.1f}KB -> {:.1f}KB gzip ({:.0f}% compression)", - pending_.size(), - static_cast(json_str.size()) / 1024.0, - static_cast(compressed.size()) / 1024.0, - (1.0 - static_cast(compressed.size()) / static_cast(json_str.size())) * 100.0); - log_->info("{}", msg); - if (console_output_) fmt::println("{}", msg); - } catch (const sqlite::sqlite_exception &e) { - log_->error("disk DB write failed: {}", e.what()); + if (console_output_) { + fmt::println("Flushed batch: {} frames, {:.1f}KB -> {:.1f}KB gzip ({:.0f}% compression)", + pending_.size(), + static_cast(json_str.size()) / 1024.0, + static_cast(compressed.size()) / 1024.0, + (1.0 - static_cast(compressed.size()) / static_cast(json_str.size())) * 100.0); + } + } catch (const sqlite::sqlite_exception &) { } pending_.clear(); @@ -157,7 +149,6 @@ void Recorder::background_flush_task(std::stop_token st) { bool mem_trigger = get_rss_mb() >= 500; if (time_trigger || mem_trigger) { - if (mem_trigger) log_->warn("RSS >= 500MB, forcing flush"); compress_batch(); } } diff --git a/src/recorder.hpp b/src/recorder.hpp index 477ad8c..35372d4 100644 --- a/src/recorder.hpp +++ b/src/recorder.hpp @@ -11,7 +11,6 @@ #include #include -#include struct FrameRecord { int64_t ts_ms; @@ -43,5 +42,4 @@ private: std::stop_source flush_stop_; std::future flush_task_; bool console_output_ = false; - std::shared_ptr log_; };