Lisp

This page documents rules for adding third-party Common and Emacs Lisp code to //piper/third_party.

General requirements

Third-party Common Lisp code goes in //piper/third_party/lisp.

Third-party Emacs Lisp code goes in //piper/third_party/elisp.

When creating a new directory, set ************************************* in the CL.

For Lisp-specific questions, email emailremoved@.

Each newly-created package should have an OWNERS file listing two people that can maintain the package, a LICENSE file containing the text of the code’s license agreement, a minimal BUILD file, a METADATA file, and a copy.bara.sky file to facilitate upgrading. Please CC emailremoved@ on your CL. They’ll make sure that everything is kosher style-wise. If you (or the reviewers) have any questions, don’t hesitate to add removed link to google group to the CL.

Common Lisp Requirements

Importing third_party code typically requires translating an ASDF .asd file into a BUILD file. There is no need to represent nested structure of the ASDF system definition; any linear order of source files suffices. To produce such an order, the following script may be followed as an example to help write a BUILD file, assuming use of SBCL and Quicklisp:

;; convert antik
(let (list)
  (sb-int:encapsulate
   'compile-file 'trace
   (lambda (realfun pathname &rest rest)
     (let ((sourceroot (namestring (truename "~/antik/"))))
       (when (eql (mismatch (namestring pathname) sourceroot)
                  (length sourceroot))
         (push (subseq (namestring pathname) (length sourceroot)) list))
       (apply realfun pathname rest))))
  (ql:quickload "antik")
  (sb-int:unencapsulate 'compile-file 'trace)
  (format t "srcs = [~%# serial~{~%~S,~}~%]~%" (reverse list))

Example output:

srcs = [
# serial
"init/package.lisp",
"init/utility.lisp",
# etc...
]

Emacs Lisp Specific Requirements

Third-party Emacs Lisp packages come from various sources and often distributed to Googlers’ workstations. You are responsible for ensuring the code is safe to use.

# Foo, a framework for frobbing Bars

load("//third_party/elisp/rules/elisp:defs.bzl", "elisp_library", "elisp_test")

package(default_visibility = ["//visibility:public"])

licenses(["restricted"])

exports_files(["LICENSE"])

elisp_library(
    name = "foo",
    srcs = ["foo.el"],
    load_path = ["."],
)

elisp_test(
    name = "foo_test",
    srcs = ["foo-test.el"],
    deps = [":foo"],
)

name is the name of the Blaze build target. After adding the elisp_library rule, you should try to build the package using blaze build :all. Note that warnings are treated like errors by default. To disable this behavior use the fatal_warnings = False attribute.

If the package’s unit tests don’t use ERT or require some special setup to run, you check in a Google-internal test driver file; see //piper/third_party/elisp/markdown_mode/google-test.el for an example. If the package doesn’t ship unit tests at all, use build_test instead of the elisp_test rule above so that Presubmit at least tries to byte-compile the package.

The directory //piper/third_party/elisp is for generic Emacs Lisp packages written by non-Googlers (either in pristine form or in a form that’s been improved for the Google environment). To add a subdirectory to the load-path you have to edit //piper/.../google.el; see go/emacs/debian#add for instructions.

Local changes make it hard to update to newer versions of third-party packages and should be avoided; prefer contributing patches upstream or, if that doesn’t work, use the advise functionality of Emacs Lisp.

To simplify updating to new versions, please add a go/copybara configuration. See //piper/third_party/elisp/kv/copy.bara.sky for an example.

If you want to use Bazel for Emacs Lisp packages outside of Google, feel free to use the rules_elisp rules.