From 133cc97e55db0286691581c6e7d1bea555a9f92b Mon Sep 17 00:00:00 2001 From: Hojun-Cho Date: Fri, 14 Aug 2026 23:17:18 +0900 Subject: [PATCH] fix(runtime): make startup and GTK installation explicit --- Dockerfile | 1 + Makefile | 35 +++++++++++-------- README.md | 68 ++++++++++++++++++++++++++++++++---- bench/Makefile | 5 +-- gtk/Makefile | 27 ++++++++++----- map/README | 3 +- run.sh | 14 +------- tests/Makefile | 93 +++++++++++++++++++++++++++++--------------------- xim/Makefile | 11 +++--- 9 files changed, 168 insertions(+), 89 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3287506..ffafff8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -19,6 +19,7 @@ RUN pacman -Syu --noconfirm --needed \ python \ ttf-dejavu \ ttf-jigmo \ + valgrind \ which \ xorg-server-xvfb \ xcb-imdkit \ diff --git a/Makefile b/Makefile index c8649fb..68de2e3 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,19 @@ CC = 9c LD = 9l -PKG_CFLAGS = $(shell pkg-config --cflags dbus-1 xkbcommon) -PKG_LIBS = $(shell pkg-config --libs dbus-1 xkbcommon) -XIM_CFLAGS = $(shell pkg-config --cflags xcb-imdkit xkbcommon-x11) -XIM_LIBS = $(shell pkg-config --libs xcb-imdkit xkbcommon-x11) -TEXT_CFLAGS = $(shell pkg-config --cflags pangocairo cairo) -TEXT_LIBS = $(shell pkg-config --libs pangocairo cairo) -POPUP_CFLAGS = $(shell pkg-config --cflags xcb-randr) -POPUP_LIBS = $(shell pkg-config --libs xcb-randr) -CFLAGS = -Wall -Wextra -O2 -g $(PKG_CFLAGS) +PKG_CONFIG ?= pkg-config +CFLAGS ?= -O2 -g +WARN_CFLAGS = -Wall -Wextra +PKG_CFLAGS = $(shell $(PKG_CONFIG) --cflags dbus-1 xkbcommon) +PKG_LIBS = $(shell $(PKG_CONFIG) --libs dbus-1 xkbcommon) +XIM_CFLAGS = $(shell $(PKG_CONFIG) --cflags xcb-imdkit xkbcommon-x11) +XIM_LIBS = $(shell $(PKG_CONFIG) --libs xcb-imdkit xkbcommon-x11) +TEXT_CFLAGS = $(shell $(PKG_CONFIG) --cflags pangocairo cairo) +TEXT_LIBS = $(shell $(PKG_CONFIG) --libs pangocairo cairo) +POPUP_CFLAGS = $(shell $(PKG_CONFIG) --cflags xcb-randr) +POPUP_LIBS = $(shell $(PKG_CONFIG) --libs xcb-randr) +PROJECT_CPPFLAGS = $(PKG_CFLAGS) +PROJECT_LDLIBS = -lthread -lbio -lxcb $(PKG_LIBS) $(TEXT_LIBS) \ + $(XIM_LIBS) $(POPUP_LIBS) PROG = strans DOCKER_IMAGE = strans-build DOCKER_RUN = docker run --rm --user "$$(id -u):$$(id -g)" \ @@ -23,13 +28,15 @@ OBJS = $(SRCS:.c=.o) $(XIMOBJS) all: $(PROG) gtk $(PROG): $(OBJS) - $(LD) -o $@ $(OBJS) -lthread -lbio -lxcb $(PKG_LIBS) $(TEXT_LIBS) \ - $(XIM_LIBS) $(POPUP_LIBS) + $(LD) $(LDFLAGS) -o $@ $(OBJS) $(PROJECT_LDLIBS) $(LDLIBS) $(OBJS): dat.h fn.h ipc.h -font.o: CFLAGS += $(TEXT_CFLAGS) -win.o: CFLAGS += $(POPUP_CFLAGS) -$(XIMOBJS): CFLAGS += -I. $(XIM_CFLAGS) +font.o: PROJECT_CPPFLAGS += $(TEXT_CFLAGS) +win.o: PROJECT_CPPFLAGS += $(POPUP_CFLAGS) +$(XIMOBJS): PROJECT_CPPFLAGS += -I. $(XIM_CFLAGS) + +%.o: %.c + $(CC) $(CPPFLAGS) $(PROJECT_CPPFLAGS) $(WARN_CFLAGS) $(CFLAGS) -c -o $@ $< clean: rm -f $(OBJS) $(PROG) diff --git a/README.md b/README.md index 6db944e..3678cad 100644 --- a/README.md +++ b/README.md @@ -41,15 +41,20 @@ XIM supports `UTF8_STRING` and `COMPOUND_TEXT`. Position clients place the popup from `XNSpotLocation`; otherwise XIM placement falls back to the bottom of the focus or client window. +The popup is an X11 window, XIM is X11-only, and GTK popup placement converts +the GTK caret to X11 root coordinates. There is no native Wayland popup +surface or Wayland caret positioning. GTK and IBus clients can still use +inline preedit where their display environment supports it. + ## Build and test -Docker is the supported build environment: +Initialize the bundled test library, then use the pinned Docker environment +for a reproducible build: ```sh git submodule update --init make docker-image make docker-build -make docker-check ``` Build output: @@ -59,9 +64,32 @@ strans daemon with IBus and XIM frontends gtk/im-strans.so GTK 3 frontend module ``` -Use `make docker-check TESTARGS=hangul` to run selected C tests. Native -`make all`, `make check`, and `make bench` are also available when the -dependencies listed in [`Dockerfile`](Dockerfile) are installed. +Tests have three tiers: + +```sh +make check # generated-map validation and focused unit tests +make check-live # one IBus, GTK, XIM, and IPC daemon smoke +make check-stress # randomized, capacity, collision, failure, and restart tests +``` + +`UNITARGS` filters only the focused C unit suite, for example +`make check UNITARGS=hangul`. It does not select or skip live and stress +tests. `make docker-check` force-rebuilds and runs all three tiers in the +container; run `make docker-image` first after changing `Dockerfile`. + +Native Linux builds require a C toolchain, Make, pkg-config, Python 3, and +cmp/diff, plus: + +- Plan 9 port (`9c`, `9l`, `libthread`, and `libbio`); +- D-Bus development files; +- XCB, XCB RandR, xcb-imdkit, xkbcommon, and xkbcommon-x11; +- Pango, PangoCairo, Cairo, and Fontconfig; +- GTK 3, plus libibus and Xlib for the live clients; +- Xvfb for the X11 live tests; +- a working `C.UTF-8` locale and fonts covering Latin, CJK, and emoji. + +The package names used by the canonical Arch Linux image are listed in +[`Dockerfile`](Dockerfile). ## Run @@ -75,12 +103,21 @@ from the build tree: ./strans map ``` +`run.sh` stays in the foreground and replaces itself with the daemon. Stop it +with `Ctrl-C` or let a service supervisor own it. It neither finds nor kills +other `strans` processes. Endpoint collisions and requested frontend startup +failures make the process exit non-zero. + +The build does not copy or install the daemon or its data. `./strans DIR` +opens `hira.map`, `kata.map`, `telex.map`, `kanji.dict`, `emoji.dict`, and +`hanja.dict` from `DIR` at runtime; `run.sh` passes the tracked `map/` +directory. Only the GTK subdirectory has install and uninstall targets. + Pango shapes the complete string and selects glyph fallback from the system font set. The popup renderer uses Pango/PangoCairo and Cairo. When `DISPLAY` is set, -`strans` starts its XIM worker in the same process. `run.sh` restarts the -existing `strans` process owned by the current user. +`strans` starts its XIM worker in the same process. Configure clients as needed: @@ -90,11 +127,21 @@ export XMODIFIERS=@im=strans # GTK 3 module doas make -C gtk install +export GTK_IM_MODULE=strans # IBus client example GLFW_IM_MODULE=ibus kitty ``` +The GTK module directory is derived from GTK's pkg-config `libdir` and binary +version. It can be overridden with `GTK_MODULE_DIR`; `DESTDIR` staging is +supported and deliberately skips the host module-cache update. Remove a +native installation with: + +```sh +doas make -C gtk uninstall +``` + strans provides its own IBus endpoint; `ibus-daemon` and fcitx are not required. Without `DISPLAY`, the daemon and IBus frontend still work, but XIM is not started and the popup is disabled. @@ -112,6 +159,13 @@ make verify-map See [`map/README`](map/README) for Hanja import and Japanese dictionary generation. +## Benchmark + +`make bench` builds `bench/bench`. With the daemon stopped, `./bench.sh` starts +one build-tree instance, warms it up, and records the workload with Linux +`perf`. It requires `perf` and permission to profile the daemon, and writes +`bench/perf.data`. + ## Licensing Third-party license notices are in [`LICENSES`](LICENSES). The repository does diff --git a/bench/Makefile b/bench/Makefile index 502dbca..451e612 100644 --- a/bench/Makefile +++ b/bench/Makefile @@ -1,8 +1,9 @@ CC = cc -CFLAGS = -Wall -O2 +CFLAGS ?= -O2 bench: main.c ../ipc.c ../ipc.h - $(CC) $(CFLAGS) -I.. -o $@ main.c ../ipc.c + $(CC) $(CPPFLAGS) -I.. -Wall $(CFLAGS) $(LDFLAGS) -o $@ \ + main.c ../ipc.c $(LDLIBS) clean: rm -f bench diff --git a/gtk/Makefile b/gtk/Makefile index 84150e2..b1283bc 100644 --- a/gtk/Makefile +++ b/gtk/Makefile @@ -1,24 +1,33 @@ PROG = im-strans.so -CFLAGS = -Wall -O2 -I.. $(shell pkg-config --cflags gtk+-3.0) -LDFLAGS = $(shell pkg-config --libs gtk+-3.0) -LIBDIR ?= /usr/lib -GTK_MODULE_DIR = $(LIBDIR)/gtk-3.0/3.0.0/immodules +PKG_CONFIG ?= pkg-config +CFLAGS ?= -O2 +GTK_CFLAGS = $(shell $(PKG_CONFIG) --cflags gtk+-3.0) +GTK_LIBS = $(shell $(PKG_CONFIG) --libs gtk+-3.0) +GTK_LIBDIR ?= $(shell $(PKG_CONFIG) --variable=libdir gtk+-3.0) +GTK_BINARY_VERSION ?= $(shell $(PKG_CONFIG) --variable=gtk_binary_version gtk+-3.0) +GTK_MODULE_DIR ?= $(GTK_LIBDIR)/gtk-3.0/$(GTK_BINARY_VERSION)/immodules +GTK_QUERY_IMMODULES ?= gtk-query-immodules-3.0 all: $(PROG) $(PROG): main.c ../ipc.c ../ipc.h - $(CC) -shared -fPIC $(CFLAGS) -o $@ main.c ../ipc.c $(LDFLAGS) + $(CC) $(CPPFLAGS) -I.. $(GTK_CFLAGS) -Wall $(CFLAGS) $(LDFLAGS) \ + -shared -fPIC -o $@ main.c ../ipc.c $(GTK_LIBS) $(LDLIBS) install: $(PROG) - test -n "$(LIBDIR)" + test -n "$(GTK_LIBDIR)" + test -n "$(GTK_BINARY_VERSION)" + test -n "$(GTK_MODULE_DIR)" mkdir -p "$(DESTDIR)$(GTK_MODULE_DIR)" cp $(PROG) "$(DESTDIR)$(GTK_MODULE_DIR)/" - if test -z "$(DESTDIR)"; then gtk-query-immodules-3.0 --update-cache; fi + if test -z "$(DESTDIR)"; then $(GTK_QUERY_IMMODULES) --update-cache; fi uninstall: - test -n "$(LIBDIR)" + test -n "$(GTK_LIBDIR)" + test -n "$(GTK_BINARY_VERSION)" + test -n "$(GTK_MODULE_DIR)" rm -f "$(DESTDIR)$(GTK_MODULE_DIR)/$(PROG)" - if test -z "$(DESTDIR)"; then gtk-query-immodules-3.0 --update-cache; fi + if test -z "$(DESTDIR)"; then $(GTK_QUERY_IMMODULES) --update-cache; fi clean: rm -f $(PROG) diff --git a/map/README b/map/README index 03bc4b8..d697f32 100644 --- a/map/README +++ b/map/README @@ -78,4 +78,5 @@ rejected; rewrite or omit those rows before import. `verifymap.py` checks UTF-8, row structure, unique keys, 64-rune keys and values, canonical candidate spacing, and duplicate dictionary candidates. -Pass it the exact `.map` and `.dict` files installed by the build. +Pass it the exact `.map` and `.dict` files used for runtime or validation. +The normal build does not install map data. diff --git a/run.sh b/run.sh index 8da97c9..9de7c90 100755 --- a/run.sh +++ b/run.sh @@ -11,16 +11,4 @@ if ! test -x ./strans; then echo "run.sh: ./strans is not executable; run make first" >&2 exit 1 fi -if ! command -v pkill >/dev/null 2>&1; then - echo "run.sh: pkill is required" >&2 - exit 1 -fi - -uid=$(id -u) || exit 1 -pkill -TERM -u "$uid" -x strans 2>/dev/null || : -sleep 0.1 -pkill -KILL -u "$uid" -x strans 2>/dev/null || : - -./strans map