夜雨聆风学习资料网

ARTICLE · 1114354

龙芯电脑下的桌面时钟编译、安装教程

龙芯电脑下的桌面时钟编译、安装教程

国庆快乐,昨天去上海博物馆看了中美洲展,今天回来继续

一、缘起

深度论坛上有一位作者用 PyQt5 写了一个桌面时钟日历挂件:大号数字时钟 + 农历 + 二十四节气 + 黄历宜忌 + 倒计时 + 番茄钟。作者的发布说明里写得很直白——嫌系统右下角的时间显示太小,就自己动手做了一个;并且明确表示"各位要是觉得需要增加功能的可以自行下载源码更改"。

原作者发布的 2.0 版压缩包里有一个 58MB 的"绿色单文件版",双击即用、不装依赖。但它是由 PyInstaller 在 x86_64 上打包的 ELF 程序,在龙芯电脑上根本无法运行:

$ file 桌面时钟 
桌面时钟: ELF 64-bit LSB executable, x86-64 ... interpreter /lib64/ld-linux-x86-64.so.2

跨架构没有捷径,只能走源码这条路。好在它是纯 Python 程序,适配成本远低于 C/C++ 程序。本文记录在龙芯 3A6000 + Loongnix 25 上把它跑起来、打成原生单文件、并配置开机自启的全过程。

特别说明:本软件的版权归原作者所有。本文仅记录在龙芯平台上运行它所需的适配改动,不改动原作者署名、不改变版权归属,也不用于任何商业用途。原帖地址见文末参考文献。

二、环境准备

2.1 本文验证环境

项目
配置
处理器
龙芯 3A6000(loongarch64,ABI 2.0 新世界)
操作系统
Loongnix GNU/Linux 25
桌面环境
XFCE 4(X11 会话)
屏幕
1920×1080,logicalDPI = 96,devicePixelRatio = 1.0
Python
3.13.5
Qt
Qt 5.15.15(libqt5core5t64 / libqt5gui5t64 / libqt5widgets5t64)
PyQt5
5.15.11(系统 apt 包 python3-pyqt5)
打包工具
PyInstaller 6.22.2(自编译 loongarch bootloader)

2.2 依赖检查

程序只依赖两个库,其中 PyQt5 是重量级依赖,zhdate 是农历计算库。

python3 -c "import PyQt5; print('PyQt5 OK')" 
python3 -c "from zhdate import ZhDate; print('zhdate OK')"

如果 PyQt5 缺失,优先用系统包安装——发行版已经为龙芯编译好了原生 Qt5,比自行编译可靠得多:

sudo apt install python3-pyqt5

zhdate 是纯 Python 包,直接用 pip 安装即可。Debian 12 及以后的系统受 PEP 668 保护,系统 Python 环境需要显式放行(或者自行创建虚拟环境):

pip3 install --user --break-system-packages zhdate
提示:程序中"全局快捷键"依赖 keyboard 库,而该库在 Linux 下需要在 root 权限下才能注册全局热键,普通用户下会静默失效。程序对此做了容错(找不到库也能正常启动),因此不必安装,用托盘图标或窗口内快捷键即可。

2.3 源码获取

从原帖提供的网盘地址下载 2.0 版压缩包(内含 shizhong.py 源码、桌面时钟.spec 打包配置、发布说明和 x86_64 绿色版),解压:

7z x 时钟.7z -o时钟 
cd 时钟 
ls 
# 发布说明.txt  桌面时钟  桌面时钟.spec  shizhong.py

三、源码适配

原作者的设计基线是"96 DPI 下的观感",并没有针对龙芯或 1080p 屏幕做验证。直接运行会暴露两个问题,另外还有一个只有打包后才会暴露的缺陷。以下改动共 4 处。

3.1 问题一:界面偏小(缩放系数)

2.0 版引入了全局缩放系数 GLOBAL_BASE,实际缩放公式为:

实际显示尺寸 = GLOBAL_BASE × (logicalDPI / 96)

本机 logicalDPI = 96,即缩放完全由 GLOBAL_BASE 决定。作者默认值 0.65 在 1080p 屏上偏小(窗口仅 416×715 像素),调到 0.85 观感更合适。

# 原作 GLOBAL_BASE = 0.65
# 适配后 GLOBAL_BASE = 0.85

3.2 问题二:底部被裁切(窗口高度小于内容高度)

这是原作的一个隐藏缺陷:窗口被写死为 640×1100,但布局的真实最小高度更大,导致最底部的倒计时一行被裁掉。用下面的脚本可以在不改动源码的情况下实测出来:

QT_QPA_PLATFORM=offscreen 
python3 - <<'PY' src = open('shizhong.py', encoding='utf-8').read() 
g = {'__name__': 'notmain'}          
# 不触发 __main__,便于只构造控件 
exec(compile(src, 'shizhong', 'exec'), g) 
from PyQt5.QtWidgets 
import QApplication app = QApplication([]) w = g['ClockCalendarWidget']() 
print('窗口固定高度 =', w.height()) 
print('内容最小高度 =', w.minimumSizeHint().height()) PY

原作实测结果:

窗口固定高度 = 1100 内容最小高度 = 1170        # 超出 70 像素,底部必被裁切

由于所有尺寸都乘以同一个缩放系数,这个 70 像素的差额在任何缩放下都存在(比例恒为 1.064)。修复方式是让窗口高度不小于内容真实高度:

# 原作 WINDOW_WIDTH = 640; WINDOW_HEIGHT = 1100 # 适配后(1170 为实测最小高度,另留少量余量以兼容不同字体度量) WINDOW_WIDTH = 640; WINDOW_HEIGHT = 1180

3.3 问题三:小屏适配(竖向收敛)

原作的 DPI 补偿只考虑横向观感,不考虑"窗口会不会超出屏幕"。补一段竖向收敛逻辑,保证在低分辨率屏幕上自动缩小而不是顶出屏幕:

scr = app.primaryScreen() ldpi = scr.logicalDotsPerInch() if scr else 96 _scale = GLOBAL_BASE * (ldpi / 96.0) 
# 竖向收敛:窗口高度不得超过屏幕可用高度(留 40px 边距) 
if scr:     _avail_h = scr.availableGeometry().height()     
if _scale * WINDOW_HEIGHT > _avail_h - 40:         
_scale = (_avail_h - 40) / WINDOW_HEIGHT globals()['_SCALE'] = _scale

3.4 问题四:打包后开机自启失效

原作的开机自启是写一个 XDG 自启动文件:

Exec=python3 {script}

在脚本方式下这行没问题。但一旦用 PyInstaller 打包成单文件可执行程序,python3 后面就跟了一个 ELF 二进制,登录时会启动失败。修复方式是区分运行形态:

def _launch_cmd():     
if getattr(sys, "frozen", False):      
# PyInstaller 打包后         
return f'"{sys.executable}"'      
 # sys.executable 即可执行文件自身     
return f'python3 "{os.path.abspath(sys.argv[0])}"'

3.5 适配后的运行效果

src="http://mmb!iz.qpic.cn/sz_mmbiz_png/CUQWWCxOKIXB1QxYILia4vI9ldKeicFXmPI8fLAe2wQw8OlN6ccpxFCu8TtTib7GNnokqt3f1NmkpGaCyGicnyWqFUC4WTphLdEKTTZS9aia9JyE/0?from=appmsg"

界面为 544×1003(1920×1080、缩放 0.85 时),底部"距离秋分还有 13 天"完整显示——这正是修复高度缺陷后带来的直接效果。

四、运行验证

源码方式直接运行:

cd 时钟/loong64 python3 shizhong.py

启动时终端会打印一行 DPI 日志,便于确认缩放是否符合预期:

[DPI] logicalDPI=96.0, devicePixelRatio=1.000, GLOBAL_BASE=0.85, scale=0.850

验收检查清单:

检查项
预期结果
窗口位置
屏幕右上角,距边缘 20 像素
窗口尺寸
544×1003(1080p 屏)
底部倒计时
完整可见,无裁切
农历与节气
显示"七月廿九 教师节"等
日历
当月日期、今日高亮、调休"班/休"标注正确
右键菜单
能弹出,含主题、透明度、番茄钟统计等入口

五、编译打包:生成龙芯原生单文件

原作者用 PyInstaller 生成了 x86_64 绿色版。那么龙芯上能不能照做?可以,但有一点必须注意:

PyPI 上没有 loongarch64 的 PyInstaller 预编译包,pip install pyinstaller 只会拉到源码包(sdist)。同时,源码包里也只预置了 Windows / macOS 的 bootloader,龙芯的 bootloader 需要自己编译。

好消息是 PyInstaller 官方代码里已经内置了龙芯架构的识别逻辑(PyInstaller/_shared_with_waf.py 中的 loongarch 分支),bootloader 源码也在源码包里,自己编译即可。

5.1 完整编译步骤

# 1) 拉取源码包(不要加 --only-binary,龙芯没有 wheel) 
pip3 download --no-deps -d /tmp/pyi pyinstaller cd /tmp/pyi && tar xzf pyinstaller-6.22.2.tar.gz  
# 2) 编译龙芯 bootloader(依赖 gcc,本项目无需额外第三方开发库) cd pyinstaller-6.22.2/bootloader python3 ./waf all 
# 产物落在 PyInstaller/bootloader/ 下: 
#   install .../PyInstaller/bootloader/Linux-64bit-loongarch/run  
# 3) 安装 PyInstaller(从本地目录安装,才会带上刚编译的 bootloader) 
pip3 install --user --break-system-packages /tmp/pyi/pyinstaller-6.22.2 
python3 -c "import PyInstaller,os;print(os.listdir(os.path.join(os.path.dirname(PyInstaller.__file__),'bootloader')))" 
# ['Darwin-64bit', 'Linux-64bit-loongarch', 'Windows-64bit-intel', 'Windows-32bit-intel', 'images']  
# 4) 打包(在源码目录执行) 
cd 时钟/loong64 
python3 -m PyInstaller --onefile --name 桌面时钟 --noconfirm shizhong.py

5.2 打包结果

$ ls -lh dist/ 
-rwxr-xr-x 1 huzhou huzhou 54M  9月10日 16:35 桌面时钟 
$ file dist/桌面时钟 
ELF 64-bit LSB executable, LoongArch, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-loongarch-lp64d.so.1

产出 54MB 的原生 LoongArch 单文件可执行程序,与原作者 x86_64 绿色版的形态一致。整个过程在 3A6000 上约 45 秒完成,其中 bootloader 编译不到 1 秒。

5.3 两种运行方式对比

方式
启动速度
依赖
适用场景
源码运行 python3 shizhong.py
快
需要系统 PyQt5 与 zhdate
日常使用、需要随时调参
单文件 dist/桌面时钟
稍慢(需解压运行时)
无(自带 Python 与 PyQt5)
拷贝到其他龙芯机器、归档留存

六、安装:启动器与开机自启

6.1 添加应用启动器

新建 桌面时钟.desktop:

[Desktop Entry] Type=Application Name=桌面时钟 Comment=桌面时钟日历挂件(农历/节气/宜忌/倒计时/番茄钟) Exec=/home/用户/桌面时钟/dist/桌面时钟 Icon=office-calendar Terminal=false Categories=Utility;Clock;

安装到应用菜单(也可直接拖到桌面):

mkdir -p ~/.local/share/applications cp 桌面时钟.desktop ~/.local/share/applications/ chmod +x ~/.local/share/applications/桌面时钟.desktop

注意 Exec= 必须写绝对路径,并按自己的实际存放位置修改。

6.2 开机自启

程序自带该功能:右键窗口 →"开机自启"。它会在 ~/.config/autostart/ 下生成 clock-calendar.desktop,内容形如:

[Desktop Entry] Type=Application Name=Clock Calendar Exec=python3 "/home/用户/桌面时钟/loong64/shizhong.py" X-GNOME-Autostart-enabled=true

使用单文件版本时,该行会自动变成可执行文件本身的路径(这一步依赖 3.4 节的修复)。取消勾选会同步删除该文件。

6.3 使用要点

操作
方式
移动窗口
左键按住窗口拖动
显示 / 隐藏
单击托盘图标,或在窗口聚焦时按 Ctrl+Alt+C
查看 / 编辑日程
单击选中日期,双击或右键编辑备注(红点标记)
管理倒计时
右键 →"管理倒计时/纪念日"
番茄钟
面板上"开始/重置",点击时间可切换专注/短休/长休
换主题、调透明度、改字体
右键菜单对应项
退出
右键 →"退出程序"
提醒:窗口是无边框工具窗,不会出现在任务栏。若桌面环境的面板没有"系统托盘"插件,请不要使用"隐藏到托盘",否则窗口会无法唤回。

七、调参速查

缩放不合适时只需改一个常量(shizhong.py 顶部):

观感
GLOBAL_BASE
1080p 下窗口尺寸
偏小
0.65(原作默认值)
416×767
适中(本文采用)
0.85
544×1003
偏大
0.95
608×1121(需 1200 以上屏幕高度)

(表中尺寸按本文适配后的窗口常量 640×1180 计算;原作窗口为 640×1100,其默认 0.65 对应 416×715。)

窗口高度超过屏幕时,3.3 节的竖向收敛逻辑会自动缩小,不会顶出屏幕。

八、小结

环节
关键点
依赖
系统包 python3-pyqt5 + pip 装 zhdate(PEP 668 需放行)
适配
改缩放系数、修正窗口高度缺陷、补竖向收敛、修正打包后自启
编译
PyInstaller 无 loongarch wheel,需先 ./waf all 编译 bootloader
产物
54MB 原生 LoongArch 单文件,形态与原作者绿色版一致
安装
XDG 启动器 + 程序内"开机自启"

原作者在 x86 平台上用几十行 PyQt5 解决了一个"系统时钟太小"的小问题,并且开放源码允许他人修改——这种分享方式本身就值得尊重。本文所做的工作,只是让这份作品在国产架构的桌面上也能正常显示,版权与功劳都属于原作者。

参考文献

1. 桌面时钟(原作者发布帖),深度论坛。[https://bbs.deepin.org.cn/post/301338](https://bbs.deepin.org.cn/post/301338)

2. PyInstaller 官方文档 — Building the bootloader。[https://pyinstaller.org/en/stable/bootloader-building.html](https://pyinstaller.org/en/stable/bootloader-building.html)

3. PEP 668 — Marking Python base environments as "externally managed"。[https://peps.python.org/pep-0668/](https://peps.python.org/pep-0668/)

4. freedesktop.org — Desktop Entry Specification(XDG Autostart)。[https://specifications.freedesktop.org/desktop-entry-spec/latest/](https://specifications.freedesktop.org/desktop-entry-spec/latest/)

软件版权归原作者所有;本文仅在原作者开源代码基础上做龙芯平台适配记录,未改变版权归属。

相关学习资料