Skip to content

Commit 4354861

Browse files
authored
Merge pull request #367 from No0ne558/master
scripts: simplify build helper to terminal-only; update changelog & CI
2 parents dc8995e + 936f388 commit 4354861

25 files changed

Lines changed: 1158 additions & 441 deletions

.github/workflows/linux-simple-builds.yml

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ jobs:
9696
run: |
9797
echo "Configuring build for ${{matrix.cxx}}..."
9898
cmake -S . -B _build_${{matrix.cxx}}_${{matrix.std}} \
99+
-DBUILD_TESTING=ON \
99100
-DCMAKE_INSTALL_PREFIX="${PWD}/_install_${{matrix.cxx}}_${{matrix.std}}" \
100101
-DCMAKE_BUILD_TYPE="${{matrix.build_type}}" \
101102
-DCMAKE_CXX_STANDARD=${{matrix.std}} \
@@ -124,8 +125,65 @@ jobs:
124125
exit $BUILD_EXIT_CODE
125126
fi
126127
128+
static-analysis:
129+
name: Static Analysis (clang-tidy)
130+
runs-on: ubuntu-24.04
131+
timeout-minutes: 30
132+
steps:
133+
- uses: actions/checkout@v4
134+
135+
- name: Install clang and tools
136+
run: |
137+
sudo apt-get update -q
138+
sudo apt-get install -y --no-install-recommends clang-18 clang-tidy-18 cmake python3 build-essential
139+
140+
- name: Configure (generate compile_commands)
141+
env:
142+
CC: clang-18
143+
CXX: clang++-18
144+
run: |
145+
cmake -S . -B _build_clangtidy -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DBUILD_TESTING=OFF -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_STANDARD=23
146+
147+
- name: Run clang-tidy and save report
148+
run: |
149+
set -e
150+
cd _build_clangtidy
151+
cp compile_commands.json ..
152+
cd ..
153+
python3 - <<'PY'
154+
import json, subprocess, sys
155+
with open('compile_commands.json') as f:
156+
comps = json.load(f)
157+
files = [c['file'] for c in comps if c['file'].startswith('src/') or c['file'].startswith('main/') or c['file'].startswith('term/') or c['file'].startswith('external/')]
158+
# limit to first 200 files to keep runtime reasonable
159+
files = files[:200]
160+
cmd = ['clang-tidy-18','-p','_build_clangtidy','-checks=-*,modernize-*,performance-*,bugprone-*,cppcoreguidelines-*'] + files
161+
print('Running clang-tidy on {} files'.format(len(files)))
162+
with open('clang-tidy-report.txt','wb') as out:
163+
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
164+
for line in p.stdout:
165+
out.write(line)
166+
rc = p.wait()
167+
sys.exit(0)
168+
PY
169+
170+
- name: Upload clang-tidy report
171+
uses: actions/upload-artifact@v4
172+
with:
173+
name: clang-tidy-report
174+
path: clang-tidy-report.txt
175+
127176
if [ -f "_build_${{matrix.cxx}}_${{matrix.std}}/vt_main" ]; then
128-
echo "Build appears successful, proceeding with install..."
177+
echo "Build appears successful, running tests..."
178+
set +e
179+
timeout 120 ctest --test-dir _build_${{matrix.cxx}}_${{matrix.std}} --output-on-failure
180+
TEST_EXIT_CODE=$?
181+
set -e
182+
if [ $TEST_EXIT_CODE -ne 0 ]; then
183+
echo "Tests failed with exit code $TEST_EXIT_CODE"
184+
exit $TEST_EXIT_CODE
185+
fi
186+
echo "Tests passed, proceeding with install..."
129187
timeout 120 cmake --build _build_${{matrix.cxx}}_${{matrix.std}} --target install
130188
else
131189
echo "Build failed - executable not found"

CMakeLists.txt

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -241,26 +241,29 @@ FetchContent_Declare(
241241
)
242242
FetchContent_MakeAvailable(magic_enum)
243243

244-
include_directories(main)
245-
include_directories(main/business)
246-
include_directories(main/hardware)
247-
include_directories(main/ui)
248-
include_directories(main/data)
249-
include_directories(zone)
250-
include_directories(src/core)
251-
include_directories(src/utils)
252-
include_directories(src/network)
253-
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
254-
include_directories(external)
255-
include_directories(/usr/include/freetype2)
244+
#include_directories(main)
245+
#include_directories(main/business)
246+
#include_directories(main/hardware)
247+
#include_directories(main/ui)
248+
#include_directories(main/data)
249+
#include_directories(zone)
250+
#include_directories(src/core)
251+
#include_directories(src/utils)
252+
#include_directories(src/network)
253+
#include_directories(${CMAKE_CURRENT_SOURCE_DIR})
254+
#include_directories(external)
255+
#include_directories(/usr/include/freetype2)
256256

257257
string(TOUPPER ${CMAKE_SYSTEM_NAME} SYSTEM_UPPER)
258258
add_definitions(-DPLATFORM="${CMAKE_SYSTEM_NAME}")
259259
add_definitions(-DVIEWTOUCH_PATH="${VIEWTOUCH_PATH}")
260+
# Previously global include directories — moved to target-scoped includes below
261+
# (converted to target_include_directories(vtcore ...) to avoid leaking includes globally)
260262
add_definitions(-DKILLALL_CMD="/usr/bin/killall")
261263
add_definitions(-DLICENSE_SERVER="${LICENSE_SERVER}")
262264
add_definitions(-D${SYSTEM_UPPER})
263265
add_definitions(-DNODRM)
266+
264267

265268
set(TERM_CREDIT credit CACHE STRING "Credit source mode. Can be credit, credit_cheq, credit_mcve")
266269

@@ -291,6 +294,7 @@ add_library(conf_file STATIC
291294
# provide xdb image data, only vt_term needs to link, as it accesses 'ImageData'
292295
add_library(image_data STATIC
293296
src/core/image_data.cc src/core/image_data.hh)
297+
target_include_directories(image_data PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
294298

295299
find_package(ZLIB REQUIRED)
296300
if(NOT ZLIB_FOUND)
@@ -437,7 +441,19 @@ add_library(vtcore
437441

438442
target_include_directories(vtcore PUBLIC
439443
${CMAKE_CURRENT_BINARY_DIR} # include generated files like build_number.h
440-
${CMAKE_CURRENT_BINARY_DIR}/_deps/magic_enum-src/include)
444+
${CMAKE_CURRENT_BINARY_DIR}/_deps/magic_enum-src/include
445+
${CMAKE_CURRENT_SOURCE_DIR}
446+
${CMAKE_CURRENT_SOURCE_DIR}/main
447+
${CMAKE_CURRENT_SOURCE_DIR}/main/business
448+
${CMAKE_CURRENT_SOURCE_DIR}/main/hardware
449+
${CMAKE_CURRENT_SOURCE_DIR}/main/ui
450+
${CMAKE_CURRENT_SOURCE_DIR}/main/data
451+
${CMAKE_CURRENT_SOURCE_DIR}/zone
452+
${CMAKE_CURRENT_SOURCE_DIR}/src/core
453+
${CMAKE_CURRENT_SOURCE_DIR}/src/utils
454+
${CMAKE_CURRENT_SOURCE_DIR}/src/network
455+
${CMAKE_CURRENT_SOURCE_DIR}/external
456+
/usr/include/freetype2)
441457
target_link_libraries(vtcore PUBLIC vt_version tz spdlog::spdlog nlohmann_json::nlohmann_json magic_enum::magic_enum)
442458

443459
add_executable(vtpos

build.sh

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# Minimal terminal-only build helper for ViewTouch
5+
# - Installs missing packages for common Linux distros (apt/dnf/yum/pacman/zypper/apk)
6+
# - Configures, builds and installs via CMake
7+
# Usage: ./build.sh [--yes|-y] [--no-deps] [--prefix PATH] [--build-type TYPE] [--jobs N]
8+
9+
PROG="$(basename "$0")"
10+
TOP_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11+
BUILD_DIR="$TOP_DIR/build"
12+
PREFIX="/usr/local"
13+
BUILD_TYPE="RelWithDebInfo"
14+
JOBS="$(nproc 2>/dev/null || echo 1)"
15+
AUTO_YES=0
16+
INSTALL_DEPS=1
17+
18+
print_help() {
19+
cat <<EOF
20+
Usage: $PROG [options]
21+
22+
Options:
23+
--yes, -y Auto-accept installing missing packages
24+
--no-deps Skip installing system dependencies
25+
--prefix PATH Install prefix (default: ${PREFIX})
26+
--build-type T CMake build type (default: ${BUILD_TYPE})
27+
--jobs N Parallel build jobs (default: number of CPU cores)
28+
-h, --help Show this help
29+
30+
Examples:
31+
# Build without installing OS packages
32+
./build.sh --no-deps
33+
34+
# Install deps (prompt) then build and install to /usr
35+
sudo ./build.sh
36+
37+
# Auto-install deps, build and install to /usr/local
38+
./build.sh --yes
39+
EOF
40+
}
41+
42+
while [[ $# -gt 0 ]]; do
43+
case "$1" in
44+
--yes|-y) AUTO_YES=1; shift ;;
45+
--no-deps) INSTALL_DEPS=0; shift ;;
46+
--prefix) PREFIX="$2"; shift 2 ;;
47+
--build-type) BUILD_TYPE="$2"; shift 2 ;;
48+
--jobs) JOBS="$2"; shift 2 ;;
49+
-h|--help) print_help; exit 0 ;;
50+
*) echo "Unknown option: $1"; print_help; exit 2 ;;
51+
esac
52+
done
53+
54+
# Package lists taken from the repo's cmake/install_dependencies.cmake
55+
DEB_PACKAGES=(cmake build-essential git libx11-dev libxft-dev libxmu-dev libxpm-dev libxrender-dev libxt-dev libmotif-dev libfreetype6-dev libfontconfig1-dev zlib1g-dev libpng-dev libjpeg-dev libgif-dev pkg-config libxext-dev libxcb1-dev)
56+
RPM_PACKAGES=(cmake gcc gcc-c++ make git libX11-devel libXft-devel libXmu-devel libXpm-devel libXrender-devel libXt-devel openmotif-devel freetype-devel fontconfig-devel zlib-devel libpng-devel libjpeg-turbo-devel giflib-devel pkgconfig libXext-devel libxcb-devel)
57+
ARCH_PACKAGES=(cmake base-devel git libx11 libxft libxmu libxpm libxrender libxt openmotif freetype2 fontconfig zlib libpng libjpeg-turbo giflib pkgconf libxext libxcb)
58+
ZYPPER_PACKAGES=(cmake gcc gcc-c++ make git libX11-devel libXft-devel libXmu-devel libXpm-devel libXrender-devel libXt-devel openmotif-devel freetype2-devel fontconfig-devel zlib-devel libpng16-devel libjpeg-devel libgif-devel pkg-config libXext-devel libxcb-devel)
59+
APK_PACKAGES=(cmake build-base git libx11-dev libxft-dev libxmu-dev libxpm-dev libxrender-dev libxt-dev openmotif-dev freetype-dev fontconfig-dev zlib-dev libpng-dev libjpeg-turbo-dev giflib-dev pkgconfig libxext-dev libxcb-dev)
60+
61+
# detect package manager and select package list
62+
PKG_MANAGER="unknown"
63+
PKGS=()
64+
if command -v apt-get >/dev/null 2>&1; then
65+
PKG_MANAGER="apt"
66+
PKGS=("${DEB_PACKAGES[@]}")
67+
elif command -v dnf >/dev/null 2>&1; then
68+
PKG_MANAGER="dnf"
69+
PKGS=("${RPM_PACKAGES[@]}")
70+
elif command -v yum >/dev/null 2>&1; then
71+
PKG_MANAGER="yum"
72+
PKGS=("${RPM_PACKAGES[@]}")
73+
elif command -v pacman >/dev/null 2>&1; then
74+
PKG_MANAGER="pacman"
75+
PKGS=("${ARCH_PACKAGES[@]}")
76+
elif command -v zypper >/dev/null 2>&1; then
77+
PKG_MANAGER="zypper"
78+
PKGS=("${ZYPPER_PACKAGES[@]}")
79+
elif command -v apk >/dev/null 2>&1; then
80+
PKG_MANAGER="apk"
81+
PKGS=("${APK_PACKAGES[@]}")
82+
elif command -v brew >/dev/null 2>&1; then
83+
PKG_MANAGER="brew"
84+
PKGS=(cmake git pkg-config)
85+
fi
86+
87+
check_installed() {
88+
local pkg="$1"
89+
case "$PKG_MANAGER" in
90+
apt)
91+
dpkg -s "$pkg" >/dev/null 2>&1 && return 0 || return 1
92+
;;
93+
dnf|yum|zypper)
94+
rpm -q "$pkg" >/dev/null 2>&1 && return 0 || return 1
95+
;;
96+
pacman)
97+
pacman -Qi "$pkg" >/dev/null 2>&1 && return 0 || return 1
98+
;;
99+
apk)
100+
apk info -e "$pkg" >/dev/null 2>&1 && return 0 || return 1
101+
;;
102+
brew)
103+
brew list "$pkg" >/dev/null 2>&1 && return 0 || return 1
104+
;;
105+
*)
106+
return 1
107+
;;
108+
esac
109+
}
110+
111+
install_missing() {
112+
local missing=("${@}")
113+
if [[ ${#missing[@]} -eq 0 ]]; then
114+
echo "All required packages appear installed."
115+
return 0
116+
fi
117+
118+
echo "Missing packages: ${missing[*]}"
119+
if [[ $AUTO_YES -ne 1 ]]; then
120+
read -r -p "Install missing packages? [y/N]: " yn
121+
[[ $yn =~ ^[Yy]$ ]] || { echo "Skipping package installation."; return 0; }
122+
fi
123+
124+
case "$PKG_MANAGER" in
125+
apt)
126+
sudo apt-get update || true
127+
if ! sudo apt-get install -y "${missing[@]}"; then
128+
for p in "${missing[@]}"; do sudo apt-get install -y "$p" || echo "Warning: failed to install $p"; done
129+
fi
130+
;;
131+
dnf)
132+
if ! sudo dnf install -y "${missing[@]}"; then
133+
for p in "${missing[@]}"; do sudo dnf install -y "$p" || echo "Warning: failed to install $p"; done
134+
fi
135+
;;
136+
yum)
137+
if ! sudo yum install -y "${missing[@]}"; then
138+
for p in "${missing[@]}"; do sudo yum install -y "$p" || echo "Warning: failed to install $p"; done
139+
fi
140+
;;
141+
pacman)
142+
sudo pacman -Syu --noconfirm || true
143+
if ! sudo pacman -S --noconfirm "${missing[@]}"; then
144+
for p in "${missing[@]}"; do sudo pacman -S --noconfirm "$p" || echo "Warning: failed to install $p"; done
145+
fi
146+
;;
147+
zypper)
148+
sudo zypper refresh || true
149+
if ! sudo zypper install -y "${missing[@]}"; then
150+
for p in "${missing[@]}"; do sudo zypper install -y "$p" || echo "Warning: failed to install $p"; done
151+
fi
152+
;;
153+
apk)
154+
if ! sudo apk add --no-cache "${missing[@]}"; then
155+
for p in "${missing[@]}"; do sudo apk add --no-cache "$p" || echo "Warning: failed to install $p"; done
156+
fi
157+
;;
158+
brew)
159+
for p in "${missing[@]}"; do brew install "$p" || echo "Warning: failed to install $p"; done
160+
;;
161+
*)
162+
echo "Unsupported package manager: $PKG_MANAGER" >&2
163+
return 1
164+
;;
165+
esac
166+
}
167+
168+
if [[ $INSTALL_DEPS -eq 1 ]]; then
169+
if [[ "$PKG_MANAGER" == "unknown" ]]; then
170+
echo "Could not detect a supported package manager. Run './check_dependencies.sh' for guidance." >&2
171+
else
172+
echo "Detected package manager: $PKG_MANAGER"
173+
# collect missing packages
174+
missing_list=()
175+
for pkg in "${PKGS[@]}"; do
176+
if ! check_installed "$pkg"; then
177+
missing_list+=("$pkg")
178+
fi
179+
done
180+
install_missing "${missing_list[@]}"
181+
fi
182+
fi
183+
184+
# Configure, build, install
185+
echo "Configuring (build dir: ${BUILD_DIR})"
186+
cmake -S "$TOP_DIR" -B "$BUILD_DIR" -DCMAKE_BUILD_TYPE="$BUILD_TYPE" -DCMAKE_INSTALL_PREFIX="$PREFIX"
187+
188+
echo "Building (jobs=${JOBS})"
189+
cmake --build "$BUILD_DIR" --parallel "$JOBS"
190+
191+
echo "Installing to ${PREFIX} (may require sudo)"
192+
sudo cmake --install "$BUILD_DIR" --prefix "$PREFIX"
193+
194+
echo "Done. If packages failed to install, run './check_dependencies.sh' for manual instructions."

docs/changelog.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,21 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1414
- Files modified: `main/data/settings.hh`, `main/data/settings.cc`, `main/ui/labels.cc`, `zone/settings_zone.cc`, `main/hardware/terminal.cc`, `zone/login_zone.cc`.
1515
- NOTE: This feature is experimental and a work in progress — bugs are likely. Use with caution and report any issues you encounter.
1616

17+
### Changed
18+
- **build.sh: Simplified terminal-only build script** (2026-04-14)
19+
- Replaced the previous interactive/TUI `build.sh` with a simplified terminal-only helper that detects the distribution's package manager, installs missing build dependencies, and runs CMake configure → build → install.
20+
- Removed duplicate content and GUI/TUI helper code; made `build.sh` executable.
21+
- Files modified: `build.sh`
22+
1723
### Fixed
24+
- **Shutdown: Prevent Xft/Xrender crash & finalize font handling (2026-04-14)**
25+
- Implemented coordinated shutdown to avoid races between Xt timers/inputs and X display close; added `app_shutting_down` flag and `update_timer_mutex` to serialize timer/input removal and re-arming.
26+
- Replaced immediate `KillTerm()/exit()` calls from input callbacks with a cooperative shutdown request so the event loop and callbacks can unwind safely.
27+
- Ensure background logging and worker threads are stopped during shutdown by calling `spdlog::shutdown()` in `Logger::Shutdown()` and shutting down the global `vt::ThreadPool` early in `KillTerm()`.
28+
- Close Xft fonts with `XftFontClose()` and call `FcFini()` after the display has been closed to prevent Xft from calling into finalized fontconfig during `XCloseDisplay`.
29+
- Files modified: `term/term_view.cc`, `src/utils/vt_logger.cc`.
30+
- Impact: reduces shutdown-time SEGVs and Xft/Xlib race conditions; follow-up: audit startup `XftFontOpenName` usages to eliminate remaining fontconfig leaks.
31+
1832
- **Auto-Update vt_data: Prevent automatic updates when disabled (2026-04-09)**
1933
- Fixed unexpected vt_data downloads/updates triggered when restarting or shutting down from non-server displays even when "Auto-Update vt_data on Startup" is OFF.
2034
- Root Cause: early startup autoupdate script executed based on `.viewtouch_config.autoupdate` before the authoritative fixed settings were consulted; restart flows that use the command file + vtrestart could relaunch `vt_main` which ran the script regardless of the UI toggle.
@@ -238,6 +252,32 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
238252

239253
- **Receipt Settings: Update Kitchen Video Print Method Label (2026-01-20)**
240254
- Updated the Receipt Settings page UI text for better clarity and user experience
255+
256+
- **Misc: Additional shutdown, Xft, and font handling fixes (2026-04-14)**
257+
- Consolidated smaller hardening and refactors to improve shutdown ordering and font handling across multiple modules.
258+
- Key changes: strengthened input/timer removal checks, added/used X11/Xft-safe helpers, improved font cache/color handling, and adjusted startup font load/close ordering.
259+
- Files modified: `loader/loader_main.cc`, `main/data/manager.cc`, `src/core/data_file.cc`, `src/core/generic_char.cc`, `src/core/xft_color_cache.cc`, `src/utils/font_check.cc`, `term/layer.cc`, `term/term_main.cc`, `src/core/x11_safe.hh`.
260+
- Deleted: `scripts/modernize_cpp23.sh`.
261+
- Impact: improves robustness of shutdown sequence and reduces races/crashes related to Xft/Xlib and fontconfig. Follow-up: audit remaining font allocations for proper `XftFontClose()` usage.
262+
263+
### Recent Maintenance (2026-04-13)
264+
265+
- **Security & Robustness:** Replaced unsafe shell usage across the codebase
266+
- Replaced uses of `system()`, `popen()`, and `execl("/bin/sh", "sh", "-c", ...)` patterns with safer APIs or exec-based helpers and proper argument lists.
267+
- Major changes include: `src/core/data_persistence_manager.cc`, `src/core/crash_report.cc`, `src/utils/utility.cc`, `term/term_view.cc`, and multiple helper scripts under `scripts/`.
268+
- Vendor patch: `external/date/src/tz.cpp` was updated to use `std::filesystem` for file/directory operations and execv/createprocess-based helpers for archive extraction instead of `std::system()`.
269+
270+
- **Build / CI:** enabled unit tests in CI and ran `ctest` locally
271+
- GitHub Actions workflow updated to configure CMake with `-DBUILD_TESTING=ON` and run `ctest` after build.
272+
- Local Debug build and unit tests executed successfully: 83/83 tests passed (2026-04-13).
273+
274+
- **CMake Modernization:** moved a subset of global include directories to target-scoped includes
275+
- Converted global `include_directories(...)` usage to `target_include_directories(...)` for `vtcore` and `image_data` to improve dependency visibility and catch missing includes earlier.
276+
277+
- **Scripts:** audited and hardened Perl/shell scripts to avoid shell interpolation and unsafe backticks
278+
- Replaced backticks and string-interpolated `system()` calls with list-form `system` or safe file I/O where appropriate (examples: `scripts/tools/update-client`, `scripts/tools/dat2txt`, `scripts/system/vtrun`).
279+
280+
These changes were committed on a feature branch for review. See the PR for detailed diffs and rationale.
241281
- **Changes Made**:
242282
- Changed label from "Kitchen Video Print Method" to "Remote Video"
243283
- Updated option names from "Unmatched"/"Matched" to "Split Checks"/"Consolidate Checks"

0 commit comments

Comments
 (0)