尽可能避免使用 hardcode 路径

可执行程序

判断某个可执行程序是否存在

不推荐做法: 根据硬编码路径判断某个文件是否存在。比如判断 QFile().exists(/usr/bin/Foo)

推荐做法:根据 PATH 寻找可执行文件, 一般不需要自行读取 PATH,比如 QT 可以使用:

Exist = !QStandardPaths::findExecutable("Foo").isEmpty();

比如 glib 可以使用 find_program_in_path。

修改示例:

执行某个可执行程序

同样,推荐用 PATH 寻找,尽量不使用绝对路径。

Qt 的 QProcess 会自动处理 PATH 环境变量,因此 QProcess::execute("/usr/bin/touch", QStringList() << sessionCacheFile) 可以直接改成 QProcess::execute("touch", QStringList() << sessionCacheFile)

修改示例:

动态库路径

尽量不要硬编码 /urs/lib

qt 应用可以使用 QLibraryInfo::location(QLibraryInfo::LibrariesPath)

头文件

绝对不要有 #include </usr/include/xxx.h> 这种代码,c/c++ 头文件会自动在 /usr/include 里寻找,直接使用 #include <xxx.h>

此外,如果库提供了 pkg-config 文件,提供的 -I 参数会指定头文件位置,如果提供 Config.cmake (cmake用)文件,一般会提供 Foo_INCLUDE_DIR 变量,如果提供 .pri (qmake 用)文件,由 QT.foo.includes 提供头文件位置。xxx.h 是相对提供的路径寻找。

对于没有提供任何开发文件的库,也可以使用 cmake 提供的 CheckIncludeFile 模块寻找头文件。

应用数据(/use/share)

/usr/share,一般保存与架构无关的只读数据。此目录同样不应该硬编码,在 XDG 规范中,这种数据的目录使用环境变量 XDG_DATA_DIRS 设置,如果读不到对应环境变量再去读取 /usr/local/share:/usr/share。

使用 qt 的应用该类型硬编码路径应该使用 QStandardPaths 或者 libqtxdg 代替。

参考:XDG Base Directory

在此目录寻找某文件,推荐使用 QStandardPaths::standardLocations 参考修改:

/usr/share/applications

直接使用 QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)

相关修改:

/usr/share/AppName

读取本应用数据,qt 软件可以使用 QStandardPaths::standardLocations(QStandardPaths::AppLocalDataLocation)

相关修改:

导入翻译

部分应用导入翻译使用了 /usr/share 示例, 应该改为使用 QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation), 此外使用了 dtk 的应用是直接用 DApplication 的 loadTranslator 导入翻译。

Shebangs

#!/bin/bash -> #!/usr/bin/env bash
#!/usr/bin/python -> #!/usr/bin/env python

并非所有系统都有 /bin 目录和 /usr/bin 目录,比如 NixOS 和 GNU Guix 操作系统。 env 可以根据环境变量 $PATH 寻找可执行程序(如 bash),比硬编码路径更加灵活,可以提高可移植性。

不过并非所有脚本都适合使用 env, 有 2 种情况:

  • 对安全性要求高的脚本(如以 root 权限运行),硬编码可以避免通过相关 PATH 让 bash 指向恶意程序。
  • 带有参数的 Shebangs 头,如 #!/usr/bin/perl -w 不能改成 #!/usr/bin/env perl -w

对除此之外的大部分的 Shebangs 脚本来说,使用 env 是更好的方案。

参考资料:

相关 issues: