[Exchange and share] Linux下的Qt程序发布流程
Tofloor
default avatar
redmibook
deepin
2024-02-15 16:58
Author

工具

  • 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 -exclude-libs=libzstd.so

输入法动态链接库

这个文件 libfcitx5platforminputcontextplugin.so 要放到 QtQCreator 下,实现对 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 下,搞应用程序发布,这可能是最简洁的方式了。

Reply Favorite View the author
All Replies

No replies yet