如何自定义 Emacs 编译时间戳(以及蹲了一个愚人节的时间戳)

你小时候走路时会跟自己玩踩线/踩格子的游戏吗?比如踩着地上的直线走,或者踩着地上的方格走,时不时走偏差了还要重新调整一下。

当我决定编译 Emacs 的时候,如果不是紧急修复问题,我会想到它的时间戳会不会是一个规律或有意义的数字(比如 2.22、3.14),不是的话我会等一等(也算是减少碳排放了)。

然而 Emacs 生成的编译时间戳 emacs-build-time 的一个小「问题」让我感到有些难忍,例如 M-x emacs-version 得到版本信息:

GNU Emacs 28.0.50 (build 2, x86_64-apple-darwin16.7.0, NS appkit-1504.84 Version 10.12.6 (Build 16G2136)) of 2020-04-01

末尾的日期是运行编译脚本的时间,这本身并没有什么不妥。但如果编译的不是刚刚获取的源代码,这个时间戳似乎存在某种误导:我 xx 时间在最新的源代码上编译了 Emacs。

而我有时候会为了开/关某个特性,需要重新编译同一份源代码,这时的时间戳的不断变动就更难忍了。

解决方法是自己定制,当然不能胡编乱造,还是要基于客观事实。所以我希望时间戳跟 commit (即 emacs-repository-version) 保持一致,无论什么时候/编译多少次,时间戳都是固定的:

if [[ ! -e lisp/site-lisp/site-start.el ]]; then
    mkdir -p lisp/site-lisp/
    REV=`git log -n 1 --no-color --pretty='format:%H' ${commit}`
    TIMESTAMP=`git log -n 1 --no-color --pretty='format:%at' ${commit}`
    cat <<EOF> lisp/site-lisp/site-start.el
;;; site-start.el ---

;; This file was generated by the build-emacs.sh --- DO NOT EDIT

(defconst emacs-repository-time $TIMESTAMP
  "Time at which repository revision was pushed.")

(setq emacs-build-time (time-convert emacs-repository-time 'list))

(setq emacs-repository-version "$REV")

(provide 'site-start)

;;; site-start.el ends here
EOF
fi

快把以上代码加入 build 脚本,一起来感受弱智般的欢乐吧。


UPDATE:

如果-Q 启动 Emacs,site-start.el 文件是不会自动加载的,所以更彻底的方法应该是:

sed -i "s/^\((defconst emacs-build-time\) (if emacs-build-system (current-time))\$/\1 (time-convert \$TIMESTAMP 'list)/" lisp/version.el
sed -i "s/^\((defvar emacs-repository-version\) nil\$/\1 \"$REV\"/" lisp/version.el
4 个赞

在 Emacs 里用 emacs-repository-version 计算出来?

(let ((default-directory source-directory))
  (with-temp-buffer
    (call-process
     "git" nil t nil
     "log" "-n" "1" "--pretty=format:%ai" emacs-repository-version)
    (buffer-string)))
;; => "2020-03-30 17:17:01 -0700"

也可以,但这样源代码就不能删了。