rules_pkg is a set of Bazel rules for building distribution packages (tar, zip, deb, rpm, …).
The core abstraction is a set of package-format-agnostic mapping rules (pkg_files,
pkg_filegroup, pkg_mkdirs, pkg_mklink) that describe what goes where in a package;
format-specific rules (pkg_tar, pkg_zip, pkg_deb, pkg_rpm) consume those descriptions.
pkg/ Runtime rules and providers (shipped in the distribution)
mappings.bzl pkg_files, pkg_filegroup, pkg_mkdirs, pkg_mklink
providers.bzl PackageVariablesInfo and other providers
private/ Internal implementation helpers (not public API)
util.bzl substitute_package_variables, setup_output_files, …
deb/ pkg_deb implementation
tar/ pkg_tar implementation
zip/ pkg_zip implementation
tests/ All tests (not shipped)
mappings/ Analysis tests for pkg_files / pkg_filegroup
tar/ Tests for pkg_tar
deb/ Tests for pkg_deb
rpm/ Tests for pkg_rpm
zip/ Tests for pkg_zip
examples/ Runnable examples (tested in CI)
docs/ Generated reference docs (do not edit by hand)
distro/ Rules to build the distribution tarball
Top-level .bzl shims (mappings.bzl, pkg.bzl, etc.) are backward-compatibility
re-exports of the files inside pkg/.
After editing any .bzl or BUILD file, run:
buildifier --lint=fix <FILE>
buildifier enforces load ordering, argument sorting, and other canonical style. It will reorder loads alphabetically; let it.
- All public rule attributes must have a
doc =string. - Use
substitute_package_variables(ctx, value)(from//pkg/private:util.bzl) to expand$(VAR)make-variable syntax in string attributes. The rule must also declare apackage_variablesattribute typedattr.label(providers = [PackageVariablesInfo]). - Prefer solutions that work for all package formats (via
pkg_files/pkg_filegroup) over format-specific additions. - Actions must not write quoted strings directly to command lines — write paths to an intermediate file instead.
- Python 3 only; no Python 2 support.
- Always import with full paths from the workspace root.
- No new third-party package dependencies — standard library only.
- No files should have trailing whitespace.
- Try to keep lines under 100 characters long.
All features and bug fixes must have tests.
Tests live in tests/mappings/mappings_test.bzl and are registered via the
mappings_analysis_tests() macro called from tests/mappings/BUILD.
- Use
pkg_files_contents_test(defined inmappings_test.bzl) to assert expected destination paths from apkg_filestarget. - Use
pkg_filegroup_contents_testto compare apkg_filegroupoutput against referencepkg_files/pkg_mkdirs/pkg_mklinktargets. - Use
generic_negative_testfor targets that are expected to fail analysis. - Add new test names to the
pkg_files_analysis_teststest suite list at the bottom ofmappings_analysis_tests().
Run them with:
bazel test //tests/mappings/...
The sample naming rule used across tests is my_package_naming in
tests/my_package_name.bzl. Load it as:
load("//tests:my_package_name.bzl", "my_package_naming")Create an instance, then wire it to the package_variables attribute of
the rule under test. Example:
my_package_naming(name = "my_vars", label = "linux_x86_64", tags = ["manual"])
pkg_files(
name = "my_files",
srcs = [...],
prefix = "usr/lib/$(label)",
package_variables = ":my_vars",
tags = ["manual"],
)bazel test //tests/tar/...
bazel test //tests/deb/...
bazel test //tests/zip/...
bazel test //tests/rpm/... # may require rpm toolchain
bazel test //tests/...
After any feature change, regenerate the reference docs before committing:
bazel build //doc_build:reference
cp bazel-bin/doc_build/reference.md docs/latest.md
Do not git commit yet — that is a separate step the user will handle.
- Import
PackageVariablesInfofrom//pkg:providers.bzlandsubstitute_package_variablesfrom//pkg/private:util.bzl. - Add to the rule attrs:
"package_variables": attr.label( doc = """See [Common Attributes](#package_variables)""", providers = [PackageVariablesInfo], ),
- In the implementation, call substitution at the top before using the value:
prefix = substitute_package_variables(ctx, ctx.attr.prefix)
- Use the substituted local variable everywhere instead of
ctx.attr.prefix. - Run
buildifier --lint=fixon the modified file. - Add analysis tests in the appropriate test file.