- C 95.9%
- Java 2.7%
- Shell 0.6%
- Makefile 0.4%
- Python 0.2%
|
Some checks failed
/ linux release (push) Successful in 20s
/ macos, resampler check (push) Successful in 48s
/ linux debug, tests (push) Successful in 1m27s
/ windows release (push) Successful in 12s
/ windows debug, tests under wine (push) Successful in 1m25s
/ android build (push) Successful in 15s
/ tests on the lab phones (push) Failing after 4m55s
|
||
|---|---|---|
| .forgejo | ||
| assets | ||
| src | ||
| test | ||
| tools | ||
| .clang-format | ||
| .gitattributes | ||
| .gitignore | ||
| android-tools.txt | ||
| API.md | ||
| build-darwin.bash | ||
| build-linux.bash | ||
| build-win32.cmd | ||
| LICENSE | ||
| LICENSE-lucide.txt | ||
| LICENSE-noto.txt | ||
| LICENSE-selawik.txt | ||
| README.md | ||
xo-app
A C89 application framework for small cross-platform apps: media players, emulators, notes, calculators, small tools. Win32 and X11 first, and Android. Software renderer first, OpenGL second. Custom window chromes, winamp style, and DPI scaling done properly.
Layout
src/- the library.src/inc/xo-app/is the API, and the contracts are in the headers' comments.API.mdhas what they all assume and a small app to start from.src/vendor/- stb, dr_libs and the Speex resampler.UPSTREAMsays where each came from and what's patched.src/java/- the Android side: the activity, the playback service, the media session and the browse service.test/- unit tests,test/desktop/for the ones that open real windows,test/manual.mdfor what has to be checked by hand.tools/-bake, which the build runs, andinspect,compare-renderers,backdropandgrab.galleryshows every UI part in the standard look, light and dark.signmakes the Ed25519 keys and signaturesxa_sign_verifychecks;signalone prints how.subset_fallback.pycuts the fallback fonts inassets/down from Noto's own files, withuv run; its top says where those come from.
Building
clang only, no MSVC. C89 with // comments: -std=c89 -pedantic -Wno-comment.
- Windows:
build-win32.cmd. Builds against the MSYS2 mingw64 sysroot,XA_SYSROOT,C:/msys64/mingw64unless it's set, with itsmingw32-make. - Linux:
build-linux.bash. Needs lld, llvm-ar and the X11, Xext, Xcursor, GL and dbus-1 development files, and Xtst for the desktop tests.win32in its arguments cross-builds for Windows with llvm-mingw's clang first on PATH,XA_SYSROOTset to itsx86_64-w64-mingw32directory, and runs what it built under Wine. - Android:
androidin either script's arguments,x86_64with it for the emulator instead of arm64-v8a. What it wants is inandroid-tools.txt. - macOS: the library doesn't build yet.
build-darwin.bash resamplebuilds and runs the SIMD resampler check (tools/resample_check.c), which is what the Mac runner does.
Both scripts compile in parallel, a job to each CPU. --serial in the arguments, or XA_JOBS=1 in the environment, builds one file at a time; XA_JOBS=N sets the count.
Output goes to out/<platform>-<config>/.
| argument | |
|---|---|
debug |
The default. |
release |
Built for size, LTO. |
test |
Builds and runs the tests. On Linux, that's test, asan, tsan and test-release one after another. On Android it runs them through adb. |
test-release |
The tests, built as release is. |
asan, tsan |
Linux only. The tests under the address and undefined, or the thread, sanitizer. |
desktop |
The desktop tests and compare-renderers. On Linux it wants xvfb-desktop on PATH; .forgejo/ci-image has one. |
desktop-asan |
Linux only. The desktop tests under asan. |
pulse |
Linux only. The audio device tests against the PulseAudio server. They add two null sinks and move the default sink about while they run. |
coverage |
Linux only. A coverage report of the unit and desktop tests. |
format, format-check |
clang-format over the code, or check it's formatted. Pinned to clang-format 23; CLANG_FORMAT names another binary. |
check |
Fails if anything in src/ but memory.c uses the app's scratch arena. |
profile |
Windows only, with a config: release profile, test profile. A build for Superluminal, into out/win32-<config>-profile/. Below. |
clean |
Deletes out/. |
XA_TEST_ARGS is passed to the test runners.
Profiling
profile builds for Superluminal. It reads symbols from a PDB, and clang and lld make one beside each exe from the mingw build as it is, no MSVC needed. Frame pointers are kept and nothing is stripped; the config's optimisation stays.
With Superluminal's API there, in C:\Program Files\Superluminal\Performance\API or wherever SUPERLUMINAL_API says, the marks in xa_profile.h reach it too: named stretches of the frame, rendering, decoding, workers and the rest, and the threads by name. Without it the build says so, the marks are nothing, and the output goes to out/win32-<config>-profile-symbols/ instead. The exe loads the API's DLL when it starts, from where the build found it or beside the exe, and runs without it; the log says which.
src/profile.mk has the flags, and an app built against xo-app includes it to build alike. Apps use the XA_PROFILE_* macros and nothing of Superluminal's.
CI
.forgejo/workflows/ci.yml runs on every push: on Linux the tests, the desktop tests and format-check, and a release build; on Windows, cross-built with llvm-mingw and run under Wine, the tests, the desktop tests and a release build; and for Android, the library and the tests built for both ABIs but not run. Its container images are built from .forgejo/ci-image.
Two jobs run on vp03, the Mac, which is where the lab phones are plugged in. macos runs the resampler check, the NEON loops against speex's C on Apple Silicon with every difference a failure, and the phone lock's own tests. phones takes the arm64 test binary the android job built and runs the whole unit suite on every phone attached, through test/phones.bash; no phone, or a phone someone else holds for more than five minutes, is skipped with a message and the job stays green, and only a failing test (or one hanging past 25 minutes) turns it red. The runner is the one labelled macos.
The phone lock
tools/phone-lock.bash is a lock per phone, shared by CI and the agents on vp03. It is a directory ~/xapa/phone-locks/SERIAL with an owner file in it, the same convention the agents' scripts already use (mkdir, write owner, rm it and rmdir at the end), so both kinds work together.
tools/phone-lock.bash take SERIAL --name N --reason R [--wait SEC] [--max SEC]
tools/phone-lock.bash release SERIAL --name N
tools/phone-lock.bash run SERIAL --name N --reason R [--wait SEC] [--max SEC] -- CMD...
tools/phone-lock.bash status [SERIAL...]
--wait is how long to wait for someone else's hold, default none; running out of it is exit status 3. --max is how long a hold may last, default 2400 s (40 minutes); after it, anyone may take the lock. A lock is also taken when the process that held it (on this host) is gone, and an agent's lock with no times in it counts as stale 40 minutes after its owner file was last written. release only removes a lock whose owner is the name given. run holds the lock for the length of a command, lets go on exit, on a signal and when the command fails, and stops the command at the maximum (status 124). test/phone-lock-test.bash shows all of it, in about half a minute.
CI copies the script to ~/xapa/bin/phone-lock on vp03 on each run.
License
Mozilla Public License 2.0, in LICENSE. The vendored files in src/vendor/ keep their own. Lief, the font in assets/, is Lady Liefy's, marked CC0 1.0. Selawik Semilight and Selawik Light, beside it and baked in as the standard look's fonts, are Microsoft's, under the SIL Open Font License 1.1, in LICENSE-selawik.txt. Noto Sans Light and Noto Sans CJK JP Light, cut down and baked in for xa_font_add_builtin_fallback, are the Noto Project Authors' and Adobe's, under the same licence, in LICENSE-noto.txt. The built-in icons in src/svg_icons.c are Lucide's, ISC, in LICENSE-lucide.txt.