工具
- patchelf
- appimagetool
- linuxdeployqt
其中,linuxdeployqt
需要编译,从源码中解除 glibc
的版本限制。然后,统一放到 /usr/local/bin/
这个目录下,方便调用。
打包 AppImage
时,最好特别强调一下 wayland
库的调用及支持,当然,最重要的是把插件拷贝齐全:
linuxdeployqt ./rimetool.AppDir/usr/share/applications/newReader.desktop -appimage -extra-plugins=iconengines,platformthemes/libqgtk3.so,platforms/libqeglfs.so,platforms/libqwayland-egl.so,platforms/libqwayland-generic.so,platforms/libqxcb.so
输入法动态链接库
这个文件 libfcitx5platforminputcontextplugin.so
要放到 Qt
及 QCreator
下,实现对 fcitx5
的支持。
但是,要用当前的 Qt
工具链来编译这个库,因为:这个库要与你的 Qt-App
对接,而跨版本可能会不兼容。
编译 fcitx5-qt
基础工具链
sudo apt install g++ gcc cmake extra-cmake-modules libgl1-mesa-dev
Qt环境变量
profile
中添加:
export QTDIR=$HOME/Qt/6.6.1/gcc_64
export PATH=$QTDIR/bin:$PATH
export LD_PLUGINS_PATH=$QTDIR/plugins:$LD_PLUGINS_PATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
export QT_DEBUG_PLUGINS=1
记得:source ~/.profile
拉源码
i5@debian:~/文档$ git clone https://github.com/fcitx/fcitx5-qt.git
正克隆到 'fcitx5-qt'...
remote: Enumerating objects: 3191, done.
remote: Counting objects: 100% (478/478), done.
remote: Compressing objects: 100% (51/51), done.
remote: Total 3191 (delta 441), reused 431 (delta 427), pack-reused 2713
接收对象中: 100% (3191/3191), 1.08 MiB | 1.74 MiB/s, 完成.
处理 delta 中: 100% (2429/2429), 完成.
i5@debian:~/文档$
修改CmakeLists
最外层的 CMakeLists.txt
:
option(ENABLE_QT4 "Enable Qt 4" Off)
option(ENABLE_QT5 "Enable Qt 5" Off)
option(ENABLE_QT6 "Enable Qt 6" On)
option(ENABLE_X11 "Enable X11 support" On)
option(BUILD_ONLY_PLUGIN "Build only plugin" On)
option(BUILD_STATIC_PLUGIN "Build plugin as static" Off)
option(WITH_FCITX_PLUGIN_NAME "Enable plugin name with fcitx" On)
option(ENABLE_QT6_WAYLAND_WORKAROUND "Enable Qt6 Wayland workaround" On)
依赖列表
- libxkbcommon-dev
- libvulkan-dev
- qt6-wayland-dev
sudo apt install libxkbcommon-dev libvulkan-dev qt6-wayland-dev
编译过程纪录
i5@debian:~/文档/fcitx5-qt/build$ cmake ..
-- The C compiler identification is GNU 12.2.0
-- The CXX compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found XCB_XCB: /usr/lib/x86_64-linux-gnu/libxcb.so (found version "")
-- Found XCB: /usr/lib/x86_64-linux-gnu/libxcb.so found components: XCB
-- Found XKBCommon_XKBCommon: /usr/lib/x86_64-linux-gnu/libxkbcommon.so (found version "")
-- Found XKBCommon: /usr/lib/x86_64-linux-gnu/libxkbcommon.so (Required is at least version "0.5.0") found components: XKBCommon
-- Found X11: /usr/include
-- Looking for XOpenDisplay in /usr/lib/x86_64-linux-gnu/libX11.so
-- Looking for XOpenDisplay in /usr/lib/x86_64-linux-gnu/libX11.so - found
-- Looking for gethostbyname
-- Looking for gethostbyname - found
-- Looking for connect
-- Looking for connect - found
-- Looking for remove
-- Looking for remove - found
-- Looking for shmat
-- Looking for shmat - found
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD
-- Performing Test CMAKE_HAVE_LIBC_PTHREAD - Success
-- Found Threads: TRUE
-- Performing Test HAVE_STDATOMIC
-- Performing Test HAVE_STDATOMIC - Success
-- Found WrapAtomic: TRUE
-- Found OpenGL: /usr/lib/x86_64-linux-gnu/libOpenGL.so
-- Found WrapOpenGL: TRUE
-- Found XKB: /usr/lib/x86_64-linux-gnu/libxkbcommon.so (Required is at least version "0.5.0")
-- Found WrapVulkanHeaders: /usr/include
-- Found Wayland_Client: /usr/lib/x86_64-linux-gnu/libwayland-client.so (found version "")
-- Found Wayland_Server: /usr/lib/x86_64-linux-gnu/libwayland-server.so (found version "")
-- Found Wayland_Cursor: /usr/lib/x86_64-linux-gnu/libwayland-cursor.so (found version "")
-- Found Wayland_Egl: /usr/lib/x86_64-linux-gnu/libwayland-egl.so (found version "")
-- Found Wayland: /usr/lib/x86_64-linux-gnu/libwayland-client.so;/usr/lib/x86_64-linux-gnu/libwayland-server.so;/usr/lib/x86_64-linux-gnu/libwayland-cursor.so;/usr/lib/x86_64-linux-gnu/libwayland-egl.so (found suitable version "1.21.0", minimum required is "1.15")
CMake Warning at /usr/share/ECM/find-modules/FindWayland.cmake:130 (message):
Could not find wayland.xml in
Call Stack (most recent call first):
/usr/share/cmake-3.25/Modules/CMakeFindDependencyMacro.cmake:47 (find_package)
/home/i5/Qt/6.6.1/gcc_64/lib/cmake/Qt6/QtPublicDependencyHelpers.cmake:36 (find_dependency)
/home/i5/Qt/6.6.1/gcc_64/lib/cmake/Qt6WaylandClient/Qt6WaylandClientDependencies.cmake:30 (_qt_internal_find_third_party_dependencies)
/home/i5/Qt/6.6.1/gcc_64/lib/cmake/Qt6WaylandClient/Qt6WaylandClientConfig.cmake:40 (include)
qt6/CMakeLists.txt:5 (find_package)
CMake Warning at /usr/share/ECM/find-modules/FindWayland.cmake:130 (message):
Could not find wayland.xml in
Call Stack (most recent call first):
/usr/share/cmake-3.25/Modules/CMakeFindDependencyMacro.cmake:47 (find_package)
/home/i5/Qt/6.6.1/gcc_64/lib/cmake/Qt6/QtPublicDependencyHelpers.cmake:36 (find_dependency)
/home/i5/Qt/6.6.1/gcc_64/lib/cmake/Qt6WaylandClient/Qt6WaylandClientDependencies.cmake:30 (_qt_internal_find_third_party_dependencies)
/home/i5/Qt/6.6.1/gcc_64/lib/cmake/Qt6WaylandClient/Qt6WaylandClientConfig.cmake:40 (include)
qt6/CMakeLists.txt:5 (find_package)
-- Found WaylandScanner: /usr/bin/wayland-scanner
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_VISIBILITY - Success
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY
-- Performing Test COMPILER_HAS_HIDDEN_INLINE_VISIBILITY - Success
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR
-- Performing Test COMPILER_HAS_DEPRECATED_ATTR - Success
-- The following OPTIONAL packages have been found:
* Qt6CoreTools (required version >= 6.6.1)
* Qt6Core (required version >= 6.0.0)
* Qt6DBusTools (required version >= 6.6.1)
* Qt6DBus (required version >= 6.0.0)
* Qt6WidgetsTools (required version >= 6.6.1)
* OpenGL
* Qt6Widgets (required version >= 6.0.0)
* XKB (required version >= 0.5.0), XKB API common to servers and clients., <http://xkbcommon.org>
* WrapVulkanHeaders
* Qt6GuiTools (required version >= 6.6.1)
* Qt6WaylandScannerTools (required version >= 6.6.1)
-- The following REQUIRED packages have been found:
* ECM (required version >= 1.4.0)
* XCB, X protocol C-language Binding, <https://xcb.freedesktop.org/>
* XKBCommon (required version >= 0.5.0), Keyboard handling library using XKB data, <http://xkbcommon.org>
* X11
* Qt6 (required version >= 6.0.0)
* Qt6Gui (required version >= 6.0.0)
* Qt6WaylandClient (required version >= 6.0.0)
* Qt6WaylandGlobalPrivate (required version >= 6.0.0)
-- Configuring done
-- Generating done
-- Build files have been written to: /home/i5/文档/fcitx5-qt/build
i5@debian:~/文档/fcitx5-qt/build$ make
[ 4%] Automatic MOC for target Fcitx5Qt6DBusAddons
[ 4%] Built target Fcitx5Qt6DBusAddons_autogen
[ 9%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/Fcitx5Qt6DBusAddons_autogen/mocs_compilation.cpp.o
[ 13%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/fcitxqtwatcher.cpp.o
[ 18%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/fcitxqtdbustypes.cpp.o
[ 22%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/fcitxqtinputcontextproxy.cpp.o
[ 27%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/fcitxqtinputcontextproxyimpl.cpp.o
[ 31%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/fcitxqtinputmethodproxy.cpp.o
[ 36%] Building CXX object qt6/dbusaddons/CMakeFiles/Fcitx5Qt6DBusAddons.dir/fcitxqtcontrollerproxy.cpp.o
[ 36%] Built target Fcitx5Qt6DBusAddons
[ 40%] Automatic MOC for target fcitx5platforminputcontextplugin-qt6
[ 40%] Built target fcitx5platforminputcontextplugin-qt6_autogen
[ 45%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitx5platforminputcontextplugin-qt6_autogen/mocs_compilation.cpp.o
[ 50%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitx4watcher.cpp.o
[ 54%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitx4inputcontextproxy.cpp.o
[ 59%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitx4inputcontextproxyimpl.cpp.o
[ 63%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitx4inputmethodproxy.cpp.o
[ 68%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/hybridinputcontext.cpp.o
[ 72%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/qfcitxplatforminputcontext.cpp.o
[ 77%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitxcandidatewindow.cpp.o
[ 81%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/fcitxtheme.cpp.o
[ 86%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/font.cpp.o
[ 90%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/qtkey.cpp.o
[ 95%] Building CXX object qt6/platforminputcontext/CMakeFiles/fcitx5platforminputcontextplugin-qt6.dir/main.cpp.o
[100%] Linking CXX shared module libfcitx5platforminputcontextplugin.so
[100%] Built target fcitx5platforminputcontextplugin-qt6
i5@debian:~/文档/fcitx5-qt/build$
- 终产物
/home/i5/文档/fcitx5-qt/build/qt6/platforminputcontext/libfcitx5platforminputcontextplugin.so
另一种选择
打包所有依赖,临时赋予环境变量给 App-Bin
可能另一种选择。
setup.sh
这个脚本,是执行程序的脚本,它被桌面快捷方式文件调用:
#!/bin/bash
export LD_LIBRARY_PATH=/opt/rimetools/Q-t/lib:/opt/rimetools/Q-t/plugins
QT_QPA_PLATFORM=xcb /opt/rimetools/newReader
显然,QT_QPA_PLATFORM=xcb
是为了避坑 wayland
,在这里也可以不添加它。
而 export LD_LIBRARY_PATH=/opt/rimetools/Q-t/lib:/opt/rimetools/Q-t/plugins
则是临时环境变量,供程序寻址。
newReader.desktop
这里显示了调用关系,而且指定了图标目录,程序类别。
[Desktop Entry]
X-VERSION=1.0
Type=Application
Name=newReader
Exec=/opt/rimetools/setup.sh
Icon=/opt/rimetools/executive/rimetool.ico
Comment=InputMethod tools
Terminal=false
Categories=System;Utility;
安装与卸载
注意,这里使用了 Dash
,因为现在很多发行版默认使用它取代 Bash
,语法细节有所区别。
- install.sh
#!/bin/dash
WBCHR_PIDS=$(pgrep newReader)
string="${WBCHR_PIDS}"
echo $WBCHR_PIDS
if [ ${string}"abc" = "abc" ]
then
echo "newReader 没有活动的进程"
else
echo "检测到 newReader 正在运行,即将杀掉!"
kill $WBCHR_PIDS
fi
if [ -d /opt/rimetools ];then
echo "rimetools 文件夹存在,将会删了它!"
sudo rm -rf /opt/rimetools
fi
sudo cp -rf rimetools /opt
sudo cp -rf /opt/rimetools/executive/newReader.desktop /usr/share/applications
sudo chmod a+x /usr/share/applications/newReader.desktop
sudo chmod a+x /opt/rimetools/newReader
sudo chmod 777 /opt/rimetools/setup.sh
sudo chmod 777 /opt/rimetools -R
sudo ln -sf /usr/lib/x86_64-linux-gnu/libGL.so.1 /usr/lib/libGL.so
echo "安置成功!"
- remove.sh
#!/bin/dash
WBCHR_PIDS=$(pgrep newReader)
string="${WBCHR_PIDS}"
echo $WBCHR_PIDS
if [ ${string}"abc" = "abc" ]
then
echo "newReader 没有活动的进程"
else
echo "检测到 newReader 正在运行,即将杀掉!"
kill $WBCHR_PIDS
fi
if [ -d /opt/rimetools ]
then
echo "rimetools 文件夹存在,将会删了它!"
sudo sudo rm -rf /opt/rimetools
fi
if [ -f /usr/share/applications/newReader.desktop ]
then
echo "newReader 快捷方式存在,将会删了它!"
sudo sudo rm -rf /usr/share/applications/newReader.desktop
fi
总之,在 Linux
下,搞应用程序发布,这可能是最简洁的方式了。