印记一瞥

Boyuan's Blog

2026年博客迁移

我的个人博客从2014年创建以来已经上线十余年了,一直使用WordPress管理其内容。随着时代发展和WordPress近期负面新闻的出现,以及PHP应用存在常年占用我的VPS的内存的问题,我最后决定将博客迁移至使用静态页面生成器并使用GitHub来托管评论功能。

旧的评论很可惜无法迁移。我选择了其中精华部分手动附在了文章的末尾。新的评论会托管在 hosiet/blog-comments 这里的讨论区中。

整体迁移工作由 Claude Code 提供了大力支持。这种基础性的事务交给它完成还是很靠谱的。

如何在2026年编译 Windows 版 qgit 软件

/posts/2026/03/13/build-qgit-on-windows-in-year-2026/qgit-mingw-showcase.png

可视化对于git工具的使用很重要,尤其在使用命令行与git仓库进行交互时,额外的一个分支历史可视化窗口可以协助使用者定位目前的工作状态,避免在分支和提交的海洋中迷失。对我个人而言,我最喜欢一款不算大众的git可视化软件:qgit。它使用Qt与C++编写,功能简单,在Linux桌面环境中轻快小巧而能够满足我的git可视化需求。一个美中不足的问题是其原作者并未提供Windows平台的原生qgit可执行程序,只有源代码,且其构建文档各处也有过时问题。鉴于我的家中工作站是Windows 11桌面,本文记录我在Windows平台上编译该款软件的操作。

鉴于众所周知的Qt公司(在用户不登录的情况下)不提供Qt6预编译版本的问题,我的基本思路是使用对Linux/类Unix用户友好的msys2开发环境并使用msys2提供的Qt6开发环境。具体时间为2026年3月,使用的qgit代码版本为2.13。基本操作如下:

  1. 正常安装msys2。
  2. 在开始菜单点击“MSYS2 MINGW64”图标启动mingw-w64开发环境。这里不能用其他环境(如ucrt64),因当前情况下msys2提供的Qt6开发工具链仍然基于mingw-w64。
  3. 安装必需工具链:pacman -Syu; pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-qt6-5compat mingw-w64-x86_64-toolchain base-devel mingw-w64-x86_64-qt6
  4. 在mingw-w64环境中正常使用cmake进行构建:mkdir build; cd build; cmake ..; ninja
    • 如果遇到有关QTextCodec的编译错误,尝试替换#include <QTextCodec>字符串为#include <QtCore5Compat/QTextCodec>
  5. 提取build/文件夹下构建完成后生成的qgit.exe。然后我们需要从mingw-w64环境中抽出运行时必需的dll文件。虽然应该有更优雅的做法,但这里我的做法是将qgit.exe可执行文件挪到单独的文件夹中然后双击运行,系统提示缺少哪个文件就去msys2环境下找哪个,注意一定是环境中/mingw64/目录下的文件。
    • 运行时报告qt.qpa.plugin: Could not find the Qt platform plugin "windows" in ""这个错误需要特殊处理:解决办法是将mingw-w64环境中的qwindows.dll文件抽出来,放到qgit.exe所在文件夹下面的platforms/子文件夹中。
    • 整理过后所涉及的文件大致如图所示: /posts/2026/03/13/build-qgit-on-windows-in-year-2026/qgit-2.13-mingw-w64-files.png
  6. 别忘了安装系统层级的git工具。直接装官网的git for windows即可。

最终启动qgit程序,运行效果如下图所示。左边是构建的Windows原生版本,右边是Windows WSL2版本。 /posts/2026/03/13/build-qgit-on-windows-in-year-2026/qgit-windows-wsl-comparison.png

使用 msmtp 和 GMail 账号部署服务器 SMTP 发信(2024年)

实验室新添加的服务器需要一个基本的邮件通知功能,也就是在某些事件发生时能够向外发送电子邮件进行通知。众所周知,配置电子邮件的基础设施通常会很麻烦。因此,我在寻找解决方案时有以下三点考虑:

  • 服务器程序发送电子邮件的接口应该通用。因此,我优先考虑使用提供了兼容/usr/sbin/sendmail命令的软件。
  • 避免额外注册邮箱账号的麻烦。因此我选择重复利用我已有的 GMail 账号。
  • 考虑 GMail 的特有限制。由于使用 Google 主密码进行 SMTP 发信身份认证的操作已经被 GMail 认为不安全而禁用了,所以这次必须变相使用用户名和密码完成 SMTP 配置。Google 提供了一个名为 App passwords 的特别功能,能够根据需要创建一个起替代作用的纯文本密码。

我最后选择的解决方案是 msmtp 配合 msmtp-mta 以及 GMail SMTP + App Passwords 组合。整个过程基本是遵循Gmail with an App Password这篇英文博客文章来部署的。 本文的配置在2024年10月有效,但无法保证永远生效。请在进行配置之前先行验证方法的有效性。

基本流程

  • 第零步:为自己的 Google 账号启用两步验证功能。
  • 第一步:访问App passwords管理页面创建一个新的 App password。完成整个步骤,得到的应当是16位固定长度的密码。
  • 第二步:在服务器上安装 msmtpmsmtp-mta 软件包。前者是核心组件,后者提供了 sendmail 命令的兼容接口。
  • 第三步:在服务器上按照正常方式配置 msmtp GMail SMTP 发信。用户名仍然使用 GMail 电子邮箱地址,密码部分直接填入16位 App password 即可。
  • 第四步:测试发信。

msmtp配置文件/etc/msmtprc示例(Debian/Ubuntu 系统)

defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt

account gmail
host smtp.gmail.com
port 465
tls_starttls off
from XXXXXX@gmail.com
user XXXXXX@gmail.com
password 1111222233334444

port 465
tls on
tls_starttls off

syslog LOG_MAIL

account default: gmail

对于基于 Debian 和 Ubuntu 的服务器,在写入配置之后,考虑按照/usr/share/doc/msmtp/README.Debian的建议执行下列命令以确保配置文件并非所有人可读:

匹兹堡自助餐/吃到饱(buffet/all you can eat)餐厅简评

Golden Corral 的单人餐,拍摄于2024年1月。

我个人下馆子并不喜欢被菜单约束住,因为总是看上去什么都想吃,但限于没有同伴总是单人用餐而无法多点几道菜。因此,我比较喜欢允许餐点自选的自助餐厅。这里我就简单评价一下截至2024年1月我在美国宾州匹兹堡地区去过的,提供自助餐(buffet)或吃到饱(all you can eat)服务的几家餐厅。列出的餐厅都是适合单人前往的,像 Hunan Bar 那种三人以上的火锅自助不在本文讨论范围内。 总的来说,匹兹堡地区的自助餐和吃到饱餐厅以中餐和印餐为主,这和美国其它地区的情况可能有所不同。除了市内商业区的餐厅外,市郊更有更多令人惊喜的自助和吃到饱餐厅可供选择。

自助餐和吃到饱的区别

汉语语境下对“自助”和“吃到饱”的定义有些模糊(详见维基百科),有时后者包括了前者。为方便起见,在本文中,我使用下面的定义:

  • 自助餐(buffet):菜品位于自助区域,需要自己使用餐盘盛取。服务员通常除了补充饮料和白水外不提供其他服务。
  • 吃到饱(all you can eat):有固定菜单,菜单中的菜品分量固定,每次用餐花费固定费用可以无限量或有限量地在菜单中选取菜品并由服务员上菜。

自助为主的餐厅

China Buffet

  • 6401 Penn Ave, Pittsburgh, PA 15206

给上班族、社畜和周围本地人提供的小型美式中餐自助门店,先付款再用餐。店面在 Bakery Square 方便停车。菜品没有什么特色,但我比较喜欢这一家方便停车的特点和相对平和的店内环境。默认会给你刀叉,需要付款时提醒老板要筷子。

Hokkaido Seafood Buffet(“北海道”)

  • 4612 Browns Hill Rd, Pittsburgh, PA 15217

匹兹堡老牌中式海鲜自助,有寿司、刺身、美式小食、中餐菜品以及水果的自助供应。晚餐比午餐更贵也提供更多菜品,主要多出来了小龙虾、蟹腿等高价海鲜。

Fortune Star

  • 4070 William Penn Hwy, Monroeville, PA 15146

位置偏远的全自助中餐(已经在 Monroeville I-376 高速尽头,快到 I-76 高速入口了。幸好从匹兹堡市内 I-376 全程高速可达,位置方便停车位多)。菜品丰富:从上古的美式中餐芙蓉蛋到炒菠菜,从刺身寿司到炸薯条,从切块牛排到罗宋汤,应有尽有。

Golden Corral

  • 900 Park Manor Blvd, Pittsburgh, PA 15205

位于去机场路上的 Robinson Town Center 中。这家餐厅其实是连锁店,提供丰富完整的经典美式自助菜品。包括各式蔬菜水果沙拉、炸鸡、塔可、热汤、热狗、烤土豆、薯条、披萨、炖牛肉、玉米棒子、玉米粒、土豆泥等等等等,以及各种甜到齁的甜点。晚餐特定时段可以无限量拿取现场煎制的牛排(通常需要排队)。 /posts/2024/01/21/pittsburgh-buffet-restaurants/PXL_20240108_222700624_x3.jpg Golden Corral 的单人餐,拍摄于2024年1月。

Hide "AMD Software" entry in Windows 11 Context Menu (right-click menu)

Background

I just bought a Lenovo 14p Gen 3 laptop with preinstalled Windows 11. Since it is an AMD-based laptop, it has an AMD configuration software installed, namely AMD Software: Adrenalin Edition. It provides several useful features for screen display. However, the annoying thing is that it adds an extra entry in Windows 11’s default Context Menu. Luckily, there is a way to block such entry without uninstalling the AMD software.

Quick guide: set up chroot environment and build Debian packages (sbuild version)

TL;DR: Pbuilder-related tools are ineffective and redundant. By installing sbuild and schroot, one can set up clean and reusable chroot environments quickly and use the sole sbuild command to build Debian source packages (using src tree or .dsc files). Fade away please pbuilder/cowbuilder; long live sbuild!

Deprecation Notice

As of early 2025, the recommended way of setting up sbuild is to utilize the unshare backend. See posts here and related announcement. The instruction below is now considered obsolete and only applies to sbuild earlier than Debian 13.

配合Git为Debian系发行版打包的正确方式

配合Git为Debian系发行版打包的正确方式教你使用正确的姿势又好又快地得到一个deb安装包

Debian这个发行版历史悠久,其软件包管理工具apt和dpkg更是作为其特色沿用至今,在保留严谨传统的同时得到了长足的发展和演进。然而正是由于其不短的历史(虽然还没到三十年,但是这样的时间跨度对于IT行业的产物已经算惊人的长了),Debian的包管理工具不可避免地存在着稍显沉重的历史包袱。一些过去的真理和守则反而成为了现在的累赘,一代又一代地误导着后来者。为了让后来者少走弯路,我在这里记录一些摸索过程中的体会和技巧,希望能够让更多人体会到Debian的魅力所在。 如果你只想了解最佳的工作流的话,请直接翻到最后面查看。但是具体工具的使用方法需要自行查找资料,或者回到前文寻找相应的内容。


打包基础知识

要打包,首先应该了解其基本原理,这是在不同发行版甚至不同操作系统中都适用的知识。 说起打包,不可避免地会让人想到编译、链接、安装、复制文件等等关键词。毕竟说到底打包的目的是为了让用户更加方便可靠地获得一个软件,其目的为安装软件,那么其手段也和手工从源代码开始安装软件的做法大同小异。

手工安装软件包的流程

如果要手工从源代码开始将这个软件安装到系统中,常见的步骤包括:

  1. 获取源代码:一般是从互联网上下载一个压缩包,或者从其它途径(如光盘等)得到。
  2. 构建之前的准备:要从源代码得到二进制的可执行程序,一般需要一些工具进行辅助,典型的工具例如编译器、连接器等等。这些工具需要事先准备好,安装在系统中。
  3. 进行构建:使用软件原作者提供的构建系统进行构建,编译、链接等环节都在这一步完成。更宽泛地说,这一步从原始的源代码得到我们需要的格式的文件(例如二进制可执行程序)。
  4. 测试:如果软件原作者提供了某些测试工具,此时可以使用测试工具对刚刚构建完成的成果进行检验。
  5. 安装:这一步通常比较简单,简单到只是复制粘贴而已。我们把构建出来的成果复制放到系统合适的位置,那么安装就完成了。

打包者参与时安装软件包的流程

说完了手工安装,我们再考虑打包者存在的场景。此时,我们希望所有的脏活累活都是由不知道在世界上哪个地方的打包者干完,作为用户,只需要一条命令(或者点一下鼠标)就能好好地安装一个软件包。一键安装,就是这么舒心。我们将原有手工安装的步骤区分成打包者的工作和用户的工作两部分:

打包者的工作

  1. 获取源代码:打包者通常需要通过可靠的途径获取源代码,避免源代码的错误与不可靠。理想的情况是软件原作者提供源代码包的散列值进行验证,或者对源代码包进行数字签名。另外,直接将源代码仓库复制一份(例如用Git管理的仓库)也是很理想的方式。
  2. 处理源代码:打包者需要对获取到的源代码进行处理,具体包括检查源文件的版权信息、构建系统的情况,并根据具体情景编写打包用的指令和信息。如果发现了源代码中的问题,打包者还需要向上游进行反馈,并考虑在构建时添加这个软件包特有的补丁。这通常是打包者耗费心血最多的地方。
  3. 尝试构建软件包:打包者使用刚才编写的指令进行构建并打包。构建已经在上面说明,而打包则是将构建的成果按照一定的关系进行组织、压缩并放入一个特定格式的文件中的过程。如果出错,还需要返回上一步重新调整。
  4. 检查软件包:即便软件包成功构建,打包者也需要对其进行检查,确保质量可靠、符合要求。有问题则需要返工重新调整。
  5. 发布软件包:打包者在确定软件包适合发布后,会通过某种途径将其向外界发布出去,供用户使用。这种发布途径可能有很多,但常见的是所谓“发行版”提供的集中式发布渠道。
  6. 跟踪并修复软件缺陷:即便完成了打包,打包者的工作也没有完成。如果接到了用户的反馈认为这个软件包有问题,打包者还需要进行跟踪调查,检查问题的发生原因,并根据实际情况进行处理,或是向原作者反馈,或是调整自己的打包方式和指令。
  7. 跟踪并发布新版本:软件的原作者可能会不时地发布这个软件的新版本。打包者需要跟踪开发流程,并在新版本发布时检查变化,为新版本再次打包并发布。

可以看出,打包者的负担大大加重了。因为打包者是用户和软件开发者之间的桥梁,需要担负沟通、检查、质检等多种任务。

用户的工作

  1. 获取软件包:用户使用某些特定的途径获取到打包者的软件包。通常这种途径由特定的“发行版”集中提供。
  2. 安装软件包:用户使用安装工具把软件包安装到系统中。

用户的负担大大减轻了,一切都是现成的,只需要“拿来”“用”就行。

Debian采用的打包基础:Makefile

正式开始介绍打包之前,我们必须提及构建系统的基石:Makefile。我们来看看维基百科对Makefile是如何介绍的:

A makefile is a file containing a set of directives used with the make build automation tool.

翻译过来,就是说这个文件包含了一系列指导make这个构建自动化工具完成其工作的命令。它使用目标(target)组织起工作流程,即为了达成某个目标需要哪些源文件、需要哪些事先完成的目标、完成这个目标需要执行哪些指令,等等。Debian 利用了Makefile作为构建的中心,整个构建打包流程就是在执行Makefile的过程中完成的。这是一个特殊的文件,其名称为debian/rules。 有一个需要注意的地方:一切Makefile中的指令都以一个制表符起始。千万不要用空格替换,会出错的。 关于Makefile的普遍编写方式,请参阅其它资料,例如陈皓的经典教程《跟我一起写Makefile》(原版PDF副本重制版)。


为Debian打包的基础知识

我们已经了解到,Debian 决定采用一个Makefile文件作为构建的核心,并围绕着这个文件开展工作。下面,我们转向更实际的例子,阐述究竟应该如何完成整个构建工作。

源码包的工作目标:.orig.tar.xz, .debian.tar.xz, .dsc

在深入具体过程之前,我们不妨先了解一下打包工作的成果应该是什么。正如标题所述,Debian 开发者辛辛苦苦工作的目标是得到这三个文件。广义上讲,它们构成了 Debian 的源码包。即,获取了这三个文件,配合工具链,任何一个人都可以从源代码按照标准化的流程进行构建并得到二进制软件包(即.deb包)。要深入了解这三个文件的内容,您可以自行查看,或者在下文中所述的 Debian 新维护人员手册中也有对应的章节。 我们知道了工作目标的外在形式,当然我们也能够认识到工作目标的内在含义。无外乎下面几个:

  • 软件开发者(上游)提供的软件源代码。
  • 目标软件包的信息。信息包括维护者、依赖关系、版本号、修订历史、等等。
  • 构建软件包的指令。大部分在debian/rules文件中给出。

在此之后我们仍然需要了解的是,为了得到目标,我们手头有哪些东西可以使用:

Fast preparation of a source-only upload for Debian

Let’s assume that you find the source code of a software for Debian with a debian/ directory included. How to prepare the .dsc package (Debian source package) used for upload quickly? I will show you here.

  1. Extract the software into a certain directory, let’s say foobar/.
  2. Repack original tarball and exclude debian/ dir using tar. Rename orig tarball as <PKGNAME>_<PKGVER>.orig.tar.{bz2,gz,lzma,xz}. Note that if your package is Debian native, you should skip this step.
  3. cd foobar/
  4. dpkg-source -b .
  5. (cd ..; debsign ./*.dsc -k<YOUR_GPG_KEY_FINGERPRINT>)
  6. dpkg-genchanges -S > ../<PKGNAME>_<PKGVER>.changes
  7. cd ..; debsign ./*.changes -k<YOUR_GPG_KEY_FINGERPRINT>

All done. You may now upload the source package with dput tool.

二次规划的MATLAB解法:quadprog函数

声明

转载自新浪博客:漂流瓶jz的博客,版权归原作者。

综述

二次规划为非线性规划的一种,若某非线性规划的目标函数为自变量 $x$ 的二次函数,约束条件又全是线性的,就称这种规划为二次规划。

问题描述

Matlab中二次规划的数学模型可表述如下:

$$\min \frac{1}{2}x^{T}Hx + f^{T} x, \quad s.t. \begin{cases} Ax \leq B \\ A_{eq} \cdot x = B_{eq} \end{cases}$$

这里 $H$ 是实对称矩阵,$f, b$ 是列向量,$A$ 是相应维数的矩阵。

quadprog()用法

Matlab中求解二次规划的函数为quadprog,其的用法如下:

x = quadprog(H,f)
x = quadprog(H,f,A,b)
x = quadprog(H,f,A,b,Aeq,beq)
x = quadprog(H,f,A,b,Aeq,beq,lb,ub)
x = quadprog(H,f,A,b,Aeq,beq,lb,ub,x0)
x = quadprog(H,f,A,b,Aeq,beq,lb,ub,x0,options)
x = quadprog(problem)
[x,fval] = quadprog(H,f,...)
[x,fval,exitflag] = quadprog(H,f,...)
[x,fval,exitflag,output] = quadprog(H,f,...)
[x,fval,exitflag,output,lambda] = quadprog(H,f,...)

$H, f$ 是把目标函数化成标准形式后得到的实对称矩阵和列向量。显然 $H$ 应当是原函数的海森矩阵。它的返回值是向量 $x$,$x_0$ 是 $x$ 的初始值;$A, B, A_{eq}, B_{eq}$ 定义了线性约束 $A \cdot x \leq B,\ A_{eq} \cdot x = B_{eq}$,如果没有线性约束,则 $A = [], B = [], A_{eq} = [], B_{eq} = []$;$LB$ 和 $UB$ 是变量 $x$ 的下界和上界。如果上界和下界没有约束,则 $LB = [], UB = []$。options 定义了优化参数,为简单起见,可以使用MATLAB的缺省参数设置。fval 是目标函数值。lambda 是Lagrange乘子,它体现哪一个约束有效。output 输出优化信息。

被雪藏的大号瑞士军刀:eric6 IDE

作为一个有跨平台强迫症和被Python惯坏的业余伪程序员,我在挑选开发桌面应用的时候果断地选择了PyQt,因为它结合了Python的强大、快速开发的特点与Qt的跨平台性质。

然而常见的图形应用程序大都需要集成开发环境(IDE)以辅助开发,在挑选IDE时我着实费了一番功夫。让我们简单地列一下现在(2016年初)能够排得上名的IDE

  • PyCharm,常见的选择,据说十分强大,然而它是JetBrains公司的产品(意味着你要结合Java使用),也存在商业版,有一种不爽的感觉。
  • Eclipse,没用过不做评价。但是还是Java
  • Python IDLE,这东西能用?

今天我要推荐的是一款不是那么出名的软件:eric6 IDE。

eric6是一款针对PythonRuby的IDE。显而易见的是,它对前者的支持更加完善。它由PyQt开发而成,官方的代码版本管理系统也使用水银(Mercurial),可谓是从上到下都在使用Python。eric采用GPL3的代码授权。其功能十分丰富,包括自动补全、代码高亮、调试、单元测试、与Qt开发工具的结合、默认集成MercurialSVN的代码版本管理工具、具有插件系统可添加插件、默认也集成了一大堆附带的小工具,甚至包括了一个网页浏览器、一个图标编辑器、一个SQL数据库客户端、一个独立的小型文本编辑器、一个可以单独启动的托盘图标守护程序、一个IRC客户端、一个截屏工具和一套简易的内网协作通信的服务端与客户端,完全体现了“集成开发环境”的含义。应当说,eric是开发Python/PyQt项目的一揽子解决方案。

安装与环境配置

既然eric是针对PyQt开发而设计的,我在这里也主要说明PyQt桌面应用的开发。其它使用方法暂且略过(实际上其他使用方法暂时没有研究)。

使用总览

很遗憾的是,eric并没有一个统一的、面向用户的使用手册,网站上提供几个PDF文档充当文档的作用。就我目前看来,这可能是因为开发者并没有精力进行手册的维护,长期以来这个项目的主要开发者与维护者都是同一个人(巴士指数接近1)。幸运的是,eric使用Qt开发,仍然提供了快被人遗忘的“What’s this?”(“这是什么?”)功能,而且帮助内容十分完整,几乎可以替代使用手册的功能。鼠标指向各个元素时,也会弹出说明用的文字。这些功能也许可以帮助使用者快速上手。

软件安装

随Linux发行版发行

各个Linux发行版都提供了较新版本的eric工具。需要注意的是,eric自己包括了一套检查新版本的工具,您可能需要禁用以使用发行版自己的管理。其实Archlinux的打包很不错,一直紧紧跟随上游,并将翻译文件单独进行了打包。Archlinux大法好!

自行安装

本部分暂时略过……

源代码与开发

eric项目的源代码保存在自托管的服务器上面,使用mercurial进行版本管理。

开发采用default分支与稳定分支双分支的方式进行,新功能在default分支开发,稳定的发行版本单独分支进行维护,并在下一个版本发行之前停止维护。同时只有两个受维护的分支。某些bug和安全更新采用手工backport的方式应用到稳定分支上。

eric项目接受外来的代码贡献和志愿者的协助翻译。如果有什么想法,可以订阅eric的邮件列表参与讨论。

国际化与本地化

项目已经包含了英语、德语、法语、俄语、捷克语、西班牙语、意大利语、土耳其语和简体中文的翻译。简体中文翻译尚不完整,希望热心人士能够协助翻译。