Skip to content
Closed
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
45 changes: 45 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Test

on:
pull_request:
push:
branches: [main, master]

jobs:
test:
name: Build and test
runs-on: ubuntu-latest
# The app ships as an Arch package built against Arch's Qt, so it's tested there.
container: archlinux:latest
defaults:
run:
shell: bash
steps:
- name: Install git for the checkout
run: pacman -Syu --noconfirm --needed git

- uses: actions/checkout@v4

- name: Install the package's dependencies
# The package lives in omarchy-pkgs, so its PKGBUILD is the one list of what the app needs and CI reads it rather than keeping a copy.
run: |
curl -fsSL "https://raw.githubusercontent.com/omacom/omarchy-pkgs/8be89db82f2cdba1d6538fadf6de81929e7c12f4/pkgbuilds/${{ github.event.repository.name }}/PKGBUILD" -o "$RUNNER_TEMP/PKGBUILD"
source "$RUNNER_TEMP/PKGBUILD"
deps=("${depends[@]}" "${makedepends[@]}" "${checkdepends[@]}")
pacman -S --noconfirm --needed base-devel cmake dbus "${deps[@]%%[<>=]*}"

- name: Set up a user and a locale like a desktop's
# Root can read any file, so tests about unreadable ones need an ordinary user, with a second group for tests that change a file's group; and the container generates no locale.
run: |
useradd -m tester
groupadd other
usermod -aG other tester
chown -R tester .
sed -i 's/^#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
locale-gen

- name: Build
run: su tester -c bin/build

- name: Test
run: su tester -c 'LANG=en_US.UTF-8 dbus-run-session -- bin/test'
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
/build/
/trials/
*.user
/pkgbuild/pkg/
/pkgbuild/src/
/pkgbuild/*.pkg.tar.*
__pycache__/
76 changes: 76 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
cmake_minimum_required(VERSION 3.21)
project(hype LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()

# Like Qt's own modules, Hype never throws or catches. Without unwinding tables
# and with link-time optimization, the installed binary is about a quarter smaller.
add_compile_options(-fno-exceptions)
add_compile_definitions(QT_NO_EXCEPTIONS)

# A Qt from Qt's installer unpacked under build/qt/ wins over an older system
# Qt, newest first, unless CMAKE_PREFIX_PATH picks another.
if(NOT CMAKE_PREFIX_PATH AND NOT DEFINED ENV{CMAKE_PREFIX_PATH})
file(GLOB bundled_qt LIST_DIRECTORIES true ${CMAKE_SOURCE_DIR}/build/qt/*/gcc_64)
list(SORT bundled_qt COMPARE NATURAL ORDER DESCENDING)
set(CMAKE_PREFIX_PATH ${bundled_qt})
endif()

find_package(Qt6 6.9 REQUIRED COMPONENTS
Core Gui Qml Quick QuickControls2 Multimedia Concurrent DBus Svg Widgets Test)
find_package(PkgConfig REQUIRED)
pkg_check_modules(WEBP REQUIRED IMPORTED_TARGET libwebp libwebpdemux)
find_package(ZLIB REQUIRED)

# Everything but main.cpp, shared by the app and the tests, so each source
# compiles once and a new file in src/ needs no line here.
file(GLOB hype_sources CONFIGURE_DEPENDS src/*.cpp src/*.h)
list(REMOVE_ITEM hype_sources ${CMAKE_SOURCE_DIR}/src/main.cpp)
add_library(hype_core STATIC ${hype_sources})
target_include_directories(hype_core PUBLIC src)
target_link_libraries(hype_core PUBLIC
Qt6::Core Qt6::Gui Qt6::Qml Qt6::Quick Qt6::QuickControls2 Qt6::Multimedia Qt6::Concurrent
Qt6::DBus Qt6::Svg PkgConfig::WEBP ZLIB::ZLIB)
target_compile_options(hype_core PUBLIC -Wall -Wextra)
set_target_properties(hype_core PROPERTIES INTERPROCEDURAL_OPTIMIZATION ON)

add_executable(hype src/main.cpp src/resources.qrc)
target_link_libraries(hype PRIVATE hype_core)
set_target_properties(hype PROPERTIES INTERPROCEDURAL_OPTIMIZATION ON)

enable_testing()

# The tests read exports back with Qt Pdf, which ships in qt6-webengine, so
# building the app alone doesn't need it; testing without it fails, not skips.
find_package(Qt6 6.9 COMPONENTS Pdf)
if(TARGET Qt6::Pdf)
# The window-level tests load the same QML as the app, so they embed it too.
add_executable(hype_tests tests/tests.cpp src/resources.qrc)
target_link_libraries(hype_tests PRIVATE hype_core Qt6::Widgets Qt6::Pdf Qt6::Test)
set_target_properties(hype_tests PROPERTIES INTERPROCEDURAL_OPTIMIZATION ON)
add_test(NAME hype_tests COMMAND hype_tests)
else()
message(WARNING "Qt Pdf was not found, so the tests can't be built; install qt6-webengine.")
add_test(NAME hype_tests COMMAND sh -c "echo 'hype_tests needs Qt Pdf, from qt6-webengine' >&2; exit 1")
endif()
# Hype draws its own controls, so the tests keep Qt's platform theme and style out of it.
set_tests_properties(hype_tests PROPERTIES ENVIRONMENT
"QT_QPA_PLATFORM=offscreen;QT_QPA_PLATFORMTHEME=generic;QT_STYLE_OVERRIDE=Fusion")

# The commands, exports and shutdown, driven through build/hype as an agent would.
# test_trials covers the trial import tools, which need their own Python packages.
find_package(Python3 COMPONENTS Interpreter)
if(Python3_FOUND)
add_test(NAME hype_commands
COMMAND ${Python3_EXECUTABLE} -m unittest test_cli test_export test_shutdown
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/tests)
else()
add_test(NAME hype_commands COMMAND sh -c "echo 'hype_commands needs Python 3' >&2; exit 1")
endif()
set_tests_properties(hype_commands PROPERTIES ENVIRONMENT QT_QPA_PLATFORM=offscreen)
11 changes: 5 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,22 +244,21 @@ The mouse wheel over the sidebar selects the previous or next slide. Home/End ju

## Run from source

To build Hype yourself, install a C++17 compiler, make, Qt 6.9 or newer, FFmpeg, and GNU source-highlight; see [the package definition](pkgbuild/PKGBUILD) for dependencies. Then:
To build Hype yourself, install a C++17 compiler, CMake, Qt 6.9 or newer, FFmpeg, and GNU source-highlight; see [the package definition in omarchy-pkgs](https://github.com/omacom/omarchy-pkgs/blob/master/pkgbuilds/hype/PKGBUILD) for dependencies. Then:

```sh
./bin/build
./build/hype open examples/welcome.md
```

`bin/build` uses a Qt toolchain under `build/qt/` when present, then falls back to `qmake6` on your PATH. It checks for Qt 6.9 or newer before compiling. Set `HYPE_QMAKE=/path/to/qmake6` to select a different toolchain.
The build uses a Qt toolchain from Qt's installer under `build/qt/` when present, newest first, then the system Qt, and checks for Qt 6.9 or newer before compiling. Set `CMAKE_PREFIX_PATH=/path/to/Qt/6.9.0/gcc_64` to select a different toolchain, and delete `build/CMakeCache.txt` when switching, since CMake remembers the Qt it found.

For a launcher entry that rebuilds this checkout when opened, run `./bin/install-dev` and choose **Hype (Development)**.

Run `./bin/test` for the regression suite. After building the tests, the presenter
check can also run with two virtual displays:
Run `./bin/test` for the regression suite: the C++ tests (`hype_tests`, which read exported PDFs back with Qt Pdf from `qt6-webengine`) and the command-line tests (`hype_commands`, in Python). Arguments go to `ctest`, so `./bin/test -R hype_commands` runs only those. Set `HYPE_GUI_TESTS=0` to skip the C++ window-level tests on a machine without multimedia. After building the tests, the presenter check can also run with two virtual displays:

```sh
HYPE_GUI_TESTS=1 QT_QPA_PLATFORMTHEME=generic QT_STYLE_OVERRIDE=Fusion \
QT_QPA_PLATFORMTHEME=generic QT_STYLE_OVERRIDE=Fusion \
QT_QPA_PLATFORM="offscreen:configfile=$PWD/tests/fixtures/presenter-screens.json" \
./build/tests/hype-tests presenterViewUsesSeparateScreens
./build/hype_tests presenterViewUsesSeparateScreens
```
46 changes: 5 additions & 41 deletions bin/build
Original file line number Diff line number Diff line change
@@ -1,42 +1,6 @@
#!/bin/sh
set -eu
ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
mkdir -p "$ROOT/build"
cd "$ROOT/build"
#!/bin/bash
set -euo pipefail

if [ -n "${HYPE_QMAKE:-}" ]; then
build_qmake=$HYPE_QMAKE
else
# Qt's installer names this executable qmake; distro packages also use qmake6.
# Version sorting keeps 6.10 ahead of 6.9 when both toolchains are installed.
build_qmake=$(
for candidate in "$ROOT"/build/qt/*/gcc_64/bin/qmake "$ROOT"/build/qt/*/gcc_64/bin/qmake6; do
if [ -x "$candidate" ]; then
printf '%s\n' "$candidate"
fi
done | sort -V | tail -n 1
)
if [ -z "$build_qmake" ]; then
build_qmake=$(command -v qmake6 || true)
fi
fi
if [ -z "$build_qmake" ]; then
printf 'Qt 6.9 or newer is required; qmake6 was not found.\n' >&2
exit 1
fi
qt_version=$("$build_qmake" -query QT_VERSION)
qt_major=${qt_version%%.*}
qt_minor=${qt_version#*.}
qt_minor=${qt_minor%%.*}
if [ "$qt_major" -lt 6 ] || { [ "$qt_major" -eq 6 ] && [ "$qt_minor" -lt 9 ]; }; then
printf 'Qt 6.9 or newer is required; %s reports Qt %s.\n' "$build_qmake" "$qt_version" >&2
exit 1
fi

"$build_qmake" "$ROOT/hype.pro"
# Objects built with another Qt version cannot be safely reused.
if [ -f Makefile ] && [ "$(cat .qmake-used 2>/dev/null || true)" != "$build_qmake" ]; then
make clean
fi
make -j"$(nproc)"
printf '%s\n' "$build_qmake" > .qmake-used
root="$(cd "$(dirname "$0")/.." && pwd)"
cmake -S "$root" -B "$root/build" -DCMAKE_BUILD_TYPE=Release >/dev/null
cmake --build "$root/build" -j"$(nproc)"
5 changes: 0 additions & 5 deletions bin/install

This file was deleted.

18 changes: 7 additions & 11 deletions bin/test
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#!/bin/sh
set -eu
ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)"
mkdir -p "$ROOT/build/tests"
cd "$ROOT/build/tests"
qmake6 "$ROOT/tests/tests.pro"
make -j"$(nproc)"
# The window-level tests catch the regressions unit tests miss, so they run by default.
# Set HYPE_GUI_TESTS=0 to skip them, e.g. on a machine without multimedia.
if [ "${HYPE_GUI_TESTS-1}" = 0 ]; then unset HYPE_GUI_TESTS; else export HYPE_GUI_TESTS=1; fi
QT_QPA_PLATFORM=offscreen QT_QPA_PLATFORMTHEME=generic QT_STYLE_OVERRIDE=Fusion ./hype-tests "$@"
#!/bin/bash
set -euo pipefail

# Arguments go to ctest, so `bin/test -V` shows every Qt test function as it runs.
root="$(cd "$(dirname "$0")/.." && pwd)"
"$root/bin/build"
QT_QPA_PLATFORM=offscreen ctest --test-dir "$root/build" --output-on-failure "$@"
28 changes: 0 additions & 28 deletions hype.pro

This file was deleted.

21 changes: 0 additions & 21 deletions pkgbuild/PKGBUILD

This file was deleted.

Loading
Loading