/rules_nixpkgs

Rules for importing Nixpkgs packages into Bazel.

Primary LanguageStarlarkApache License 2.0Apache-2.0

Nixpkgs rules for Bazel

Build status

Use Nix and the Nixpkgs package set to import external dependencies (like system packages) into Bazel hermetically. If the version of any dependency changes, Bazel will correctly rebuild targets, and only those targets that use the external dependencies that changed.

Links:

Rules

Setup

Add the following to your WORKSPACE file, and select a $COMMIT accordingly.

http_archive(
    name = "io_tweag_rules_nixpkgs",
    strip_prefix = "rules_nixpkgs-$COMMIT",
    urls = ["https://github.com/tweag/rules_nixpkgs/archive/$COMMIT.tar.gz"],
)

load("@io_tweag_rules_nixpkgs//nixpkgs:repositories.bzl", "rules_nixpkgs_dependencies")
rules_nixpkgs_dependencies()

load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_git_repository", "nixpkgs_package", "nixpkgs_cc_configure")

load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl", "nixpkgs_go_configure") # optional

If you use rules_nixpkgs to configure a toolchain then you will also need to configure the build platform to include the @io_tweag_rules_nixpkgs//nixpkgs/constraints:support_nix constraint. For example by adding the following to .bazelrc:

build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host

Example

nixpkgs_git_repository(
    name = "nixpkgs",
    revision = "17.09", # Any tag or commit hash
    sha256 = "" # optional sha to verify package integrity!
)

nixpkgs_package(
    name = "hello",
    repositories = { "nixpkgs": "@nixpkgs//:default.nix" }
)

Rules

Rules for importing Nixpkgs packages.

nixpkgs_git_repository

nixpkgs_git_repository(name, remote, revision, sha256)

Name a specific revision of Nixpkgs on GitHub or a local checkout.

Attributes

name

Name; required

A unique name for this repository.

remote

String; optional

The URI of the remote Git repository. This must be a HTTP URL. There is currently no support for authentication. Defaults to upstream nixpkgs.

revision

String; required

Git commit hash or tag identifying the version of Nixpkgs to use.

sha256

String; optional

The SHA256 used to verify the integrity of the repository.

nixpkgs_local_repository

nixpkgs_local_repository(name, nix_file, nix_file_content, nix_file_deps)

Create an external repository representing the content of Nixpkgs, based on a Nix expression stored locally or provided inline. One of nix_file or nix_file_content must be provided.

Attributes

name

Name; required

A unique name for this repository.

nix_file

Label; optional

A file containing an expression for a Nix derivation.

nix_file_content

String; optional

An expression for a Nix derivation.

nix_file_deps

List of labels; optional

Dependencies of nix_file if any.

nixpkgs_cc_configure

nixpkgs_cc_configure(name, attribute_path, nix_file, nix_file_content, nix_file_deps, repositories,
                     repository, nixopts, quiet, fail_not_supported, exec_constraints,
                     target_constraints, register)

Use a CC toolchain from Nixpkgs. No-op if not a nix-based platform.

By default, Bazel auto-configures a CC toolchain from commands (e.g. gcc) available in the environment. To make builds more hermetic, use this rule to specify explicitly which commands the toolchain should use.

Specifically, it builds a Nix derivation that provides the CC toolchain tools in the bin/ path and constructs a CC toolchain that uses those tools. Tools that aren't found are replaced by ${coreutils}/bin/false. You can inspect the resulting @<name>_info//:CC_TOOLCHAIN_INFO to see which tools were discovered.

This rule depends on rules_cc.

Note: You need to configure --crosstool_top=@<name>//:toolchain to activate this toolchain.

Parameters

name

optional. default is "local_config_cc"

attribute_path

optional. default is ""

optional, string, Obtain the toolchain from the Nix expression under this attribute path. Requires nix_file or nix_file_content.

nix_file

optional. default is None

optional, Label, Obtain the toolchain from the Nix expression defined in this file. Specify only one of nix_file or nix_file_content.

nix_file_content

optional. default is ""

optional, string, Obtain the toolchain from the given Nix expression. Specify only one of nix_file or nix_file_content.

nix_file_deps

optional. default is []

optional, list of Label, Additional files that the Nix expression depends on.

repositories

optional. default is {}

dict of Label to string, Provides <nixpkgs> and other repositories. Specify one of repositories or repository.

repository

optional. default is None

Label, Provides <nixpkgs>. Specify one of repositories or repository.

nixopts

optional. default is []

optional, list of string, Extra flags to pass when calling Nix. Subject to location expansion, any instance of $(location LABEL) will be replaced by the path to the file ferenced by LABEL relative to the workspace root.

quiet

optional. default is False

bool, Whether to hide nix-build output.

fail_not_supported

optional. default is True

bool, Whether to fail if nix-build is not available.

exec_constraints

optional. default is None

Constraints for the execution platform.

target_constraints

optional. default is None

Constraints for the target platform.

register

optional. default is True

bool, enabled by default, Whether to register (with register_toolchains) the generated toolchain and install it as the default cc_toolchain.

nixpkgs_cc_configure_deprecated

nixpkgs_cc_configure_deprecated(repository, repositories, nix_file, nix_file_deps, nix_file_content,
                                nixopts)

Use a CC toolchain from Nixpkgs. No-op if not a nix-based platform.

Tells Bazel to use compilers and linkers from Nixpkgs for the CC toolchain. By default, Bazel auto-configures a CC toolchain from commands available in the environment (e.g. gcc). Overriding this autodetection makes builds more hermetic and is considered a best practice.

Example

nixpkgs_cc_configure(repository = "@nixpkgs//:default.nix")

Parameters

repository

optional. default is None

A repository label identifying which Nixpkgs to use. Equivalent to repositories = { "nixpkgs": ...}.

repositories

optional. default is {}

A dictionary mapping NIX_PATH entries to repository labels.

Setting it to

repositories = { "myrepo" : "//:myrepo" }

for example would replace all instances of <myrepo> in the called nix code by the path to the target "//:myrepo". See the relevant section in the nix manual for more information.

Specify one of repository or repositories.

nix_file

optional. default is None

An expression for a Nix environment derivation. The environment should expose all the commands that make up a CC toolchain (cc, ld etc). Exposes all commands in stdenv.cc and binutils by default.

nix_file_deps

optional. default is None

Dependencies of nix_file if any.

nix_file_content

optional. default is None

An expression for a Nix environment derivation.

nixopts

optional. default is []

Options to forward to the nix command.

nixpkgs_java_configure

nixpkgs_java_configure(name, attribute_path, java_home_path, repository, repositories, nix_file,
                       nix_file_content, nix_file_deps, nixopts, fail_not_supported, quiet, toolchain,
                       toolchain_name, toolchain_version, exec_constraints, target_constraints)

Define a Java runtime provided by nixpkgs.

Creates a nixpkgs_package for a java_runtime instance. Optionally, you can also create & register a Java toolchain. This only works with Bazel >= 5.0 Bazel can use this instance to run JVM binaries and tests, refer to the Bazel documentation for details.

Example

Bazel 4

Add the following to your WORKSPACE file to import a JDK from nixpkgs:

load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_java_configure")
nixpkgs_java_configure(
    attribute_path = "jdk11.home",
    repository = "@nixpkgs",
)

Add the following configuration to .bazelrc to enable this Java runtime:

build --javabase=@nixpkgs_java_runtime//:runtime
build --host_javabase=@nixpkgs_java_runtime//:runtime
# Adjust this to match the Java version provided by this runtime.
# See `bazel query 'kind(java_toolchain, @bazel_tools//tools/jdk:all)'` for available options.
build --java_toolchain=@bazel_tools//tools/jdk:toolchain_java11
build --host_java_toolchain=@bazel_tools//tools/jdk:toolchain_java11
Bazel 5

Add the following to your WORKSPACE file to import a JDK from nixpkgs:

load("@io_tweag_rules_nixpkgs//nixpkgs:nixpkgs.bzl", "nixpkgs_java_configure")
nixpkgs_java_configure(
    attribute_path = "jdk11.home",
    repository = "@nixpkgs",
    toolchain = True,
    toolchain_name = "nixpkgs_java",
    toolchain_version = "11",
)

Add the following configuration to .bazelrc to enable this Java runtime:

build --host_platform=@io_tweag_rules_nixpkgs//nixpkgs/platforms:host
build --java_runtime_version=nixpkgs_java
build --tool_java_runtime_version=nixpkgs_java

Parameters

name

optional. default is "nixpkgs_java_runtime"

The name-prefix for the created external repositories.

attribute_path

optional. default is None

string, The nixpkgs attribute path for jdk.home.

java_home_path

optional. default is ""

optional, string, The path to JAVA_HOME within the package.

repository

optional. default is None

See nixpkgs_package.

repositories

optional. default is {}

See nixpkgs_package.

nix_file

optional. default is None

optional, Label, Obtain the runtime from the Nix expression defined in this file. Specify only one of nix_file or nix_file_content.

nix_file_content

optional. default is ""

optional, string, Obtain the runtime from the given Nix expression. Specify only one of nix_file or nix_file_content.

nix_file_deps

optional. default is None

See nixpkgs_package.

nixopts

optional. default is []

See nixpkgs_package.

fail_not_supported

optional. default is True

See nixpkgs_package.

quiet

optional. default is False

See nixpkgs_package.

toolchain

optional. default is False

Create & register a Bazel toolchain based on the Java runtime.

toolchain_name

optional. default is None

The name of the toolchain that can be used in --java_runtime_version.

toolchain_version

optional. default is None

The version of the toolchain that can be used in --java_runtime_version.

exec_constraints

optional. default is None

Constraints for the execution platform.

target_constraints

optional. default is None

Constraints for the target platform.

nixpkgs_package

nixpkgs_package(name, attribute_path, nix_file, nix_file_deps, nix_file_content, repository,
                repositories, build_file, build_file_content, nixopts, quiet, fail_not_supported,
                kwargs)

Make the content of a Nixpkgs package available in the Bazel workspace.

If repositories is not specified, you must provide a nixpkgs clone in nix_file or nix_file_content.

Parameters

name

required.

A unique name for this repository.

attribute_path

optional. default is ""

Select an attribute from the top-level Nix expression being evaluated. The attribute path is a sequence of attribute names separated by dots.

nix_file

optional. default is None

A file containing an expression for a Nix derivation.

nix_file_deps

optional. default is []

Dependencies of nix_file if any.

nix_file_content

optional. default is ""

An expression for a Nix derivation.

repository

optional. default is None

A repository label identifying which Nixpkgs to use. Equivalent to repositories = { "nixpkgs": ...}

repositories

optional. default is {}

A dictionary mapping NIX_PATH entries to repository labels.

Setting it to

repositories = { "myrepo" : "//:myrepo" }

for example would replace all instances of <myrepo> in the called nix code by the path to the target "//:myrepo". See the relevant section in the nix manual for more information.

Specify one of repository or repositories.

build_file

optional. default is None

The file to use as the BUILD file for this repository.

Its contents are copied copied into the file BUILD in root of the nix output folder. The Label does not need to be named BUILD, but can be.

For common use cases we provide filegroups that expose certain files as targets:

:bin
Everything in the bin/ directory.
:lib
All .so and .a files that can be found in subdirectories of lib/.
:include
All .h files that can be found in subdirectories of bin/.

If you need different files from the nix package, you can reference them like this:

package(default_visibility = [ "//visibility:public" ])
filegroup(
    name = "our-docs",
    srcs = glob(["share/doc/ourpackage/**/*"]),
)

See the bazel documentation of filegroup and glob.

build_file_content

optional. default is ""

Like build_file, but a string of the contents instead of a file name.

nixopts

optional. default is []

Extra flags to pass when calling Nix.

quiet

optional. default is False

Whether to hide the output of the Nix command.

fail_not_supported

optional. default is True

If set to True (default) this rule will fail on platforms which do not support Nix (e.g. Windows). If set to False calling this rule will succeed but no output will be generated.

kwargs

optional.

nixpkgs_python_configure

nixpkgs_python_configure(name, python2_attribute_path, python2_bin_path, python3_attribute_path,
                         python3_bin_path, repository, repositories, nix_file_deps, nixopts,
                         fail_not_supported, quiet, exec_constraints, target_constraints)

Define and register a Python toolchain provided by nixpkgs.

Creates nixpkgs_packages for Python 2 or 3 py_runtime instances and a corresponding py_runtime_pair and toolchain. The toolchain is automatically registered and uses the constraint:

"@io_tweag_rules_nixpkgs//nixpkgs/constraints:support_nix"

Parameters

name

optional. default is "nixpkgs_python_toolchain"

The name-prefix for the created external repositories.

python2_attribute_path

optional. default is None

The nixpkgs attribute path for python2.

python2_bin_path

optional. default is "bin/python"

The path to the interpreter within the package.

python3_attribute_path

optional. default is "python3"

The nixpkgs attribute path for python3.

python3_bin_path

optional. default is "bin/python"

The path to the interpreter within the package.

repository

optional. default is None

See nixpkgs_package.

repositories

optional. default is {}

See nixpkgs_package.

nix_file_deps

optional. default is None

See nixpkgs_package.

nixopts

optional. default is []

See nixpkgs_package.

fail_not_supported

optional. default is True

See nixpkgs_package.

quiet

optional. default is False

See nixpkgs_package.

exec_constraints

optional. default is None

Constraints for the execution platform.

target_constraints

optional. default is None

Constraints for the target platform.

nixpkgs_sh_posix_configure

nixpkgs_sh_posix_configure(name, packages, kwargs)

Create a POSIX toolchain from nixpkgs.

Loads the given Nix packages, scans them for standard Unix tools, and generates a corresponding sh_posix_toolchain.

Make sure to call nixpkgs_sh_posix_configure before sh_posix_configure, if you use both. Otherwise, the local toolchain will always be chosen in favor of the nixpkgs one.

Parameters

name

optional. default is "nixpkgs_sh_posix_config"

Name prefix for the generated repositories.

packages

optional. default is ["stdenv.initialPath"]

List of Nix attribute paths to draw Unix tools from.

kwargs

optional.

Rules for importing a Go toolchain from Nixpkgs.

NOTE: The following rules must be loaded from @io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl to avoid unnecessary dependencies on rules_go for those who don't need go toolchain. io_bazel_rules_go must be available for loading before loading of @io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl.

nixpkgs_go_configure

nixpkgs_go_configure(sdk_name, repository, repositories, nix_file, nix_file_deps, nix_file_content,
                     nixopts, fail_not_supported, quiet)

Use go toolchain from Nixpkgs.

By default rules_go configures the go toolchain to be downloaded as binaries (which doesn't work on NixOS), there is a way to tell rules_go to look into environment and find local go binary which is not hermetic. This command allows to setup a hermetic go sdk from Nixpkgs, which should be considered as best practice. Cross toolchains are declared and registered for each entry in the PLATFORMS constant in rules_go.

Note that the nix package must provide a full go sdk at the root of the package instead of in $out/share/go, and also provide an empty normal file named ROOT at the root of package.

Example

nixpkgs_go_configure(repository = "@nixpkgs//:default.nix")

Example (optional nix support when go is a transitive dependency):

# .bazel-lib/nixos-support.bzl
def _has_nix(ctx):
    return ctx.which("nix-build") != None

def _gen_imports_impl(ctx):
    ctx.file("BUILD", "")

    imports_for_nix = """
        load("@io_tweag_rules_nixpkgs//nixpkgs:toolchains/go.bzl", "nixpkgs_go_configure")

        def fix_go():
            nixpkgs_go_configure(repository = "@nixpkgs")
    """
    imports_for_non_nix = """
        def fix_go():
            # if go isn't transitive you'll need to add call to go_register_toolchains here
            pass
    """

    if _has_nix(ctx):
        ctx.file("imports.bzl", imports_for_nix)
    else:
        ctx.file("imports.bzl", imports_for_non_nix)

_gen_imports = repository_rule(
    implementation = _gen_imports_impl,
    attrs = dict(),
)

def gen_imports():
    _gen_imports(
        name = "nixos_support",
    )

# WORKSPACE

// ...
http_archive(name = "io_tweag_rules_nixpkgs", ...)
// ...
local_repository(
    name = "bazel_lib",
    path = ".bazel-lib",
)
load("@bazel_lib//:nixos-support.bzl", "gen_imports")
gen_imports()
load("@nixos_support//:imports.bzl", "fix_go")
fix_go()

Parameters

sdk_name

optional. default is "go_sdk"

Go sdk name to pass to rules_go

repository

optional. default is None

A repository label identifying which Nixpkgs to use. Equivalent to repositories = { "nixpkgs": ...}.

repositories

optional. default is {}

A dictionary mapping NIX_PATH entries to repository labels.

Setting it to

repositories = { "myrepo" : "//:myrepo" }

for example would replace all instances of <myrepo> in the called nix code by the path to the target "//:myrepo". See the relevant section in the nix manual for more information.

Specify one of path or repositories.

nix_file

optional. default is None

An expression for a Nix environment derivation. The environment should expose the whole go SDK (bin, src, ...) at the root of package. It also must contain a ROOT file in the root of pacakge.

nix_file_deps

optional. default is None

Dependencies of nix_file if any.

nix_file_content

optional. default is None

An expression for a Nix environment derivation.

nixopts

optional. default is []

fail_not_supported

optional. default is True

See nixpkgs_package.

quiet

optional. default is False

Whether to hide the output of the Nix command.