0%

Setup ibus-hangul on Yocto Zeus

At work my boss wanted me to add Korean input method on the current embedded Linux system for Korean customers. So, this post is about how I make it happen using ibus-hangul with Yocto Zeus release.

Goal

Users should be able to switch to Korean input method by external keyboard or onboard keyboard on embedded Yocto Linux system.

Environment

Input Method Framework

There are several input method frameworks out there, such as SCIM, IBUS, fcitx .. etc. I have worked on fcitx for traditional Chinese several years ago on my chromebook (Linux using crouton). As I remember, the experience was not good.

This time, based on our requirement/environment, I did a quick research and found out that iBus might be the easiest one to get it done, and it seems to have better support for Yocto. Also, there is someone who regularly updates ibus-hangul and libhangul github repos, which is good. At least, it should be less buggy.

iBus

OpenEmbedded Layer Index is always the first place to go if you want to find any recipe. As you can see here, it has iBus support for Dunfell (Yocto version 3.1), but not for Zeus (Yocto version 3.0). So, there will be some work for us to do on Zeus.

In my case, I did a quick test on Dunfell for iBus with ibus-hangul and libhangul. After making sure everything works as what I expect, I then brought all the dependencies and changes to Zeus. The rest of the post is all based on Zeus.

Yocto Layer

In order to get some dependencies from openembedded layer for iBus, we need to ensure the following layers are included in bblayers.conf.

1
2
BBLAYERS += "${BSPDIR}/sources/meta-openembedded/meta-gnome"
BBLAYERS += "${BSPDIR}/sources/meta-openembedded/meta-networking"

iBus Dependencies

According to iBus recipe, we should be able to figure out dependencies for iBus.

In addition to ibus, we also need gettext-0.20.1 and unicode-ucd packages, which are not there for Zeus. So, we should bring those recipes as well to our meta layer. It should look like below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
our-meta-layer

├── recipes-core
│ ├── gettext
│ │ ├── gettext-0.20.1
│ │ │ ├── 0001-init-env.in-do-not-add-C-CXX-parameters.patch
│ │ │ ├── 0001-msgmerge-Fix-behaviour-of-for-msgfmt-on-PO-files-wit.patch
│ │ │ ├── 0001-tests-autopoint-3-unset-MAKEFLAGS.patch
│ │ │ ├── add-with-bisonlocaledir.patch
│ │ │ ├── cr-statement.c-timsort.h-fix-formatting-issues.patch
│ │ │ ├── parallel.patch
│ │ │ ├── run-ptest
│ │ │ ├── serial-tests-config.patch
│ │ │ └── use-pkgconfig.patch
│ │ └── gettext_0.20.1.bb
│ │
└── recipes-support
├── ibus
│ ├── files
│ │ └── ibus
│ ├── ibus
│ │ └── 0001-Do-not-try-to-start-dbus-we-do-not-have-dbus-lauch.patch
│ ├── ibus.bb
│ ├── ibus.bbappend
│ ├── ibus.inc
│ └── ibus-native.bb
└── unicode-ucd
├── files
│ └── license.html
└── unicode-ucd_12.1.0.bb

Other dependencies we need for iBus should be available on Zeus. We just have to add the list to our image recipe as below.

1
2
3
4
5
6
7
8
9
10
11
12
13
IBUS_DEPEND_PKGS = " \
gsettings-desktop-schemas \
iso-codes \
librsvg-gtk \
python3-pygobject \
\
matchbox-keyboard-im \
setxkbmap \
"
IMAGE_INSTALL += " \
${IBUS_DEPEND_PKGS} \
ibus \
"

Startup Script

In order to get ibus started when system is up, we need to have a startup script as below.

/our-meta-layer/recipes-support/ibus/files/ibus
1
2
3
#!/bin/sh
/usr/bin/dconf update
/usr/bin/ibus-daemon -xrv &

Then, we need to create a bbappend file to include the script we just created.

/our-meta-layer/recipes-support/ibus/ibus.bbappend
1
2
3
4
5
6
7
8
9
10
11
12
13
MAINTAINER = "Joseph Chen <jocodoma@gmail.com>"

SRC_URI += "file://ibus"

do_configure_prepend() {
sed -i 's/\@PYTHON\@/\/usr\/bin\/python3/' ${S}/setup/ibus-setup.in
}

do_install_append() {
# the scrip to start ibus daemon
install -d ${D}/${sysconfdir}/X11/Xsession.d
install -m 0755 ${WORKDIR}/ibus ${D}/${sysconfdir}/X11/Xsession.d/89ibus_daemon.sh
}

ibus-hangul

To create a recipe for ibus-hangul, we use devtool.

/our-meta-layer/recipes-support/ibus-hangul/ibus-hangul_git.bb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
SUMMARY = "ibus-hangul is a Korean input method engine for IBus"
HOMEPAGE = "https://github.com/libhangul/ibus-hangul"

MAINTAINER = "Joseph Chen <jocodoma@gmail.com>"

LICENSE = "GPLv2"
LIC_FILES_CHKSUM = "file://COPYING;md5=751419260aa954499f7abaabaa882bbe"

SRC_URI = "git://github.com/libhangul/ibus-hangul;protocol=https"

PV = "1.5.3+git${SRCPV}"
SRCREV = "24eecbcdc015a90c9e6fc5b33201f6e899ae556c"

DEPENDS = "gtk+3 ibus libhangul"

S = "${WORKDIR}/git"

do_configure_prepend() {
touch ${S}/ABOUT-NLS
sed -i 's/\@PYTHON\@/\/usr\/bin\/python3/' ${S}/setup/ibus-setup-hangul.in
}

inherit autotools gettext pkgconfig

# Specify any options you want to pass to the configure script using EXTRA_OECONF:
EXTRA_OECONF = ""

FILES_${PN} += "/usr/share/"

Above is the recipe that I created. The only changes I made is to modify the python3 path on target in order to get ibus-setup-hangul script works correctly on target.

libhangul

Again, to create a recipe for libhangul, we use devtool.

/our-meta-layer/recipes-support/libhangul/libhangul_git.bb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
SUMMARY = "A library to support hangul input method logic, hanja dictionary and small hangul character classification"
HOMEPAGE = "https://github.com/libhangul/libhangul"

MAINTAINER = "Joseph Chen <jocodoma@gmail.com>"

LICENSE = "LGPLv2.1"
LIC_FILES_CHKSUM = "file://COPYING;md5=a6f89e2100d9b6cdffcea4f398e37343"

SRC_URI = "git://github.com/libhangul/libhangul;protocol=https"

PV = "0.1.0+git${SRCPV}"
SRCREV = "2ddc547f014afdc25b73a2f26f28b70728d79105"

DEPENDS = "libcheck intltool-native expat"

S = "${WORKDIR}/git"

do_configure_prepend() {
touch ${S}/ChangeLog
touch ${S}/config.rpath
}

inherit gettext pkgconfig autotools

# Specify any options you want to pass to the configure script using EXTRA_OECONF:
EXTRA_OECONF = ""

Image Recipe

After we get ibus-hangul and libhangul recipes ready, we then add these two recipes to our image recipe.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
IBUS_DEPEND_PKGS = " \
gsettings-desktop-schemas \
iso-codes \
librsvg-gtk \
python3-pygobject \
\
matchbox-keyboard-im \
setxkbmap \
"

IBUS_HANGUL_PKGS = " \
${IBUS_DEPEND_PKGS} \
ibus \
ibus-hangul \
libhangul \
"

IMAGE_INSTALL += " \
${IBUS_HANGUL_PKGS}
"

dconf

dconf is a low-level configuration system and settings management tool. Its main purpose is to provide a back end to GSettings on platforms that don’t already have configuration storage systems. It depends on GLib. It is part of GNOME 3 and is a replacement for GConf.

– from Wikipedia - dconf

Once we have iBus or ibus-hangul up and running on our target device, we should be able to make some changes via setup scripts:

To launch setup page for iBus:

1
TARGET$ /usr/bin/ibus-setup

To launch setup page for ibus-hangul:

1
TARGET$ /usr/bin/ibus-setup-hangul

After we are done with the setup, the settings will be saved in /home/root/.config/dconf/user.

We can also add the settings to Yocto recipe as a default settings. Make sure we also update dconf in startup script.

/our-meta-layer/recipes-support/ibus-hangul/ibus-hangul_git.bbappend
1
2
3
4
5
6
7
8
9
10
11
12
13
14
MAINTAINER = "Joseph Chen <jocodoma@gmail.com>"

SRC_URI += "file://user"

do_install_append() {
# default settings for ibus / ibus-hangul
install -d ${D}/home/root/.config/dconf
install -m 0644 ${WORKDIR}/user ${D}/home/root/.config/dconf/user
}

# Specify any options you want to pass to the configure script using EXTRA_OECONF:
EXTRA_OECONF += ""

FILES_${PN} += "/home/root/.config/dconf/user"

References: