Code Monkey home page Code Monkey logo

rules_nixpkgs's Introduction

Nixpkgs rules for Bazel

Continuous integration

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:

See examples for how to use rules_nixpkgs with different toolchains.

Rules

Setup

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

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

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 @rules_nixpkgs_core//constraints:support_nix constraint. For example by adding the following to .bazelrc:

build --host_platform=@rules_nixpkgs_core//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" }
)

Migration from older releases

path Attribute (removed in 0.3)

path was an attribute from the early days of rules_nixpkgs, and its ability to reference arbitrary paths is a danger to build hermeticity.

Replace it with either nixpkgs_git_repository if you need a specific version of nixpkgs. If you absolutely must depend on a local folder, use Bazel's local_repository workspace rule. Both approaches work well with the repositories attribute of nixpkgs_package.

local_repository(
  name = "local-nixpkgs",
  path = "/path/to/nixpkgs",
)

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

Reference documentation

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, cc_lang, cc_std, cross_cpu)

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.

If you specify the nix_file or nix_file_content argument, the CC toolchain is discovered by evaluating the corresponding expression. In addition, you may use the attribute_path argument to select an attribute from the result of the expression to use as the CC toolchain (see example below).

If neither the nix_file nor nix_file_content argument is used, the toolchain is discovered from the stdenv.cc and the stdenv.cc.bintools attributes of the given <nixpkgs> repository.

# use GCC 11
nixpkgs_cc_configure(
  repository = "@nixpkgs",
  nix_file_content = "(import <nixpkgs> {}).gcc11",
)
# use GCC 11 (same result as above)
nixpkgs_cc_configure(
  repository = "@nixpkgs",
  attribute_path = "gcc11",
  nix_file_content = "import <nixpkgs> {}",
)
# alternate usage without specifying `nix_file` or `nix_file_content`
nixpkgs_cc_configure(
  repository = "@nixpkgs",
  attribute_path = "gcc11",
)
# use the `stdenv.cc` compiler (the default of the given @nixpkgs repository)
nixpkgs_cc_configure(
  repository = "@nixpkgs",
)

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. Uses default repository if no nix_file or nix_file_content is provided.

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. See nixopts attribute to nixpkgs_package for further details.

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.

cc_lang

optional. default is "c++"

string, "c++" by default. Used to populate CXX_FLAG so the compiler is called in C++ mode. Can be set to "none" together with appropriate copts in the cc_library call: see above.

cc_std

optional. default is "c++0x"

string, "c++0x" by default. Used to populate CXX_FLAG so the compiler uses the given language standard. Can be set to "none" together with appropriate copts in the cc_library call: see above.

cross_cpu

optional. default is ""

string, "" by default. Used if you want to add a cross compilation C/C++ toolchain. Set this to the CPU architecture for the target CPU. For example x86_64, would be k8.

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_flake_package

nixpkgs_flake_package(name, nix_flake_file, nix_flake_lock_file, nix_flake_file_deps, package,
                      build_file, build_file_content, nixopts, quiet, fail_not_supported,
                      legacy_path_syntax, kwargs)

Make the content of a local Nix Flake package available in the Bazel workspace.

IMPORTANT NOTE: Calling nix build copies the entirety of the Nix Flake into the Nix Store. When using the path: syntax, this means the directory containing flake.nix and any subdirectories. Without specifying path: Nix may infer that the flake is the Git repository and copy the entire thing. As a consequence, you may want to isolate your flake from the rest of the repository to minimize the amount of unnecessary data that gets copied into the Nix Store whenever the flake is rebuilt.

Parameters

name

required.

A unique name for this repository.

nix_flake_file

required.

Label to flake.nix that will be evaluated.

nix_flake_lock_file

required.

Label to flake.lock that corresponds to nix_flake_file.

nix_flake_file_deps

optional. default is []

Additional dependencies of nix_flake_file if any.

package

optional. default is None

Nix Flake package to make available. The default package will be used if not specified.

build_file

optional. default is None

The file to use as the BUILD file for this repository. See nixpkgs_package for more information.

build_file_content

optional. default is ""

Like build_file, but a string of the contents instead of a file name. See nixpkgs_package for more information.

nixopts

optional. default is []

Extra flags to pass when calling Nix. See nixpkgs_package for more information.

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.

legacy_path_syntax

optional. default is False

If set to True (not default), the Nix Flake invocation will directly call nix build <path> instead of nix build path:<path> which may involve copying the entirety of the Git repo into the Nix Store instead of just the path and its children.

kwargs

optional.

Common rule arguments.

nixpkgs_git_repository

nixpkgs_git_repository(name, revision, remote, sha256, kwargs)

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

Parameters

name

required.

String

A unique name for this repository.

revision

required.

String

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

remote

optional. default is "https://github.com/NixOS/nixpkgs"

String

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

sha256

optional. default is None

String

The SHA256 used to verify the integrity of the repository.

kwargs

optional.

Additional arguments to forward to the underlying repository rule.

nixpkgs_http_repository

nixpkgs_http_repository(name, url, urls, auth, strip_prefix, integrity, sha256, kwargs)

Download a Nixpkgs repository over HTTP.

Parameters

name

required.

String

A unique name for this repository.

url

optional. default is None

String

A URL to download the repository from.

This must be a file, http or https URL. Redirections are followed.

More flexibility can be achieved by the urls parameter that allows to specify alternative URLs to fetch from.

urls

optional. default is None

List of String

A list of URLs to download the repository from.

Each entry must be a file, http or https URL. Redirections are followed.

URLs are tried in order until one succeeds, so you should list local mirrors first. If all downloads fail, the rule will fail.

auth

optional. default is None

Dict of String

An optional dict mapping host names to custom authorization patterns.

If a URL's host name is present in this dict the value will be used as a pattern when generating the authorization header for the http request. This enables the use of custom authorization schemes used in a lot of common cloud storage providers.

The pattern currently supports 2 tokens: <login> and <password>, which are replaced with their equivalent value in the netrc file for the same host name. After formatting, the result is set as the value for the Authorization field of the HTTP request.

Example attribute and netrc for a http download to an oauth2 enabled API using a bearer token:

auth_patterns = {
    "storage.cloudprovider.com": "Bearer <password>"
}

netrc:

machine storage.cloudprovider.com
        password RANDOM-TOKEN

The final HTTP request would have the following header:

Authorization: Bearer RANDOM-TOKEN

strip_prefix

optional. default is None

String

A directory prefix to strip from the extracted files.

Many archives contain a top-level directory that contains all of the useful files in archive. This field can be used to strip it from all of the extracted files.

For example, suppose you are using nixpkgs-22.11.zip, which contains the directory nixpkgs-22.11/ under which there is the default.nix file and the pkgs/ directory. Specify strip_prefix = "nixpkgs-22.11" to use the nixpkgs-22.11 directory as your top-level directory.

Note that if there are files outside of this directory, they will be discarded and inaccessible (e.g., a top-level license file). This includes files/directories that start with the prefix but are not in the directory (e.g., nixpkgs-22.11.release-notes). If the specified prefix does not match a directory in the archive, Bazel will return an error.

integrity

optional. default is None

String

Expected checksum in Subresource Integrity format of the file downloaded.

This must match the checksum of the file downloaded. It is a security risk to omit the checksum as remote files can change. At best omitting this field will make your build non-hermetic. It is optional to make development easier but either this attribute or sha256 should be set before shipping.

sha256

optional. default is None

String The expected SHA-256 of the file downloaded.

This must match the SHA-256 of the file downloaded. It is a security risk to omit the SHA-256 as remote files can change. At best omitting this field will make your build non-hermetic. It is optional to make development easier but should be set before shipping.

kwargs

optional.

Additional arguments to forward to the underlying repository rule.

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,
                       register, 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
Bazel 6

with with Bzlmod

Add the following to your MODULE.bazel file to depend on rules_nixpkgs, rules_nixpkgs_java, and nixpgks:

bazel_dep(name = "rules_nixpkgs_core", version = "0.12.0")
bazel_dep(name = "rules_nixpkgs_java", version = "0.12.0")
bazel_dep(name = "rules_java", version = "7.3.1")
bazel_dep(name = "platforms", version = "0.0.9")

nix_repo = use_extension("@rules_nixpkgs_core//extensions:repository.bzl", "nix_repo")
nix_repo.github(
    name = "nixpkgs",
    org = "NixOS",
    repo = "nixpkgs",
    commit = "ff0dbd94265ac470dda06a657d5fe49de93b4599",
    sha256 = "1bf0f88ee9181dd993a38d73cb120d0435e8411ea9e95b58475d4426c0948e98",
)
use_repo(nix_repo, "nixpkgs")

non_module_dependencies = use_extension("//:non_module_dependencies.bzl", "non_module_dependencies")
use_repo(non_module_dependencies, "nixpkgs_java_runtime_toolchain")

register_toolchains("@nixpkgs_java_runtime_toolchain//:all")

archive_override(
    module_name = "rules_nixpkgs_java",
    urls = "https://github.com/tweag/rules_nixpkgs/releases/download/v0.12.0/rules_nixpkgs-0.12.0.tar.gz",
    integrity = "",
    strip_prefix = "rules_nixpkgs-0.12.0/toolchains/java",
)

Add the following to a .bzl file, like non_module_dependencies.bzl, to import a JDK from nixpkgs:

load("@rules_nixpkgs_java//:java.bzl", "nixpkgs_java_configure")

def _non_module_dependencies_impl(_ctx):
    nixpkgs_java_configure(
        name = "nixpkgs_java_runtime",
        attribute_path = "openjdk19.home",
        repository = "@nixpkgs",
        toolchain = True,
        toolchain_name = "nixpkgs_java",
        toolchain_version = "19",
        register = False,
    )

non_module_dependencies = module_extension(
    implementation = _non_module_dependencies_impl,
)

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

common --enable_bzlmod
build --host_platform=@rules_nixpkgs_core//platforms:host
build --java_runtime_version=nixpkgs_java_19
build --tool_java_runtime_version=nixpkgs_java_19
build --java_language_version=19
build --tool_java_language_version=19

with WORKSPACE

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_11
build --tool_java_runtime_version=nixpkgs_java_11
build --java_language_version=11
build --tool_java_language_version=11
Bazel 7 with Bzlmod

Add the following to your MODULE.bazel file to depend on rules_nixpkgs, rules_nixpkgs_java, and nixpgks:

bazel_dep(name = "rules_nixpkgs_core", version = "0.12.0")
bazel_dep(name = "rules_nixpkgs_java", version = "0.12.0")
bazel_dep(name = "rules_java", version = "7.5.0")
bazel_dep(name = "platforms", version = "0.0.9")

nix_repo = use_extension("@rules_nixpkgs_core//extensions:repository.bzl", "nix_repo")
nix_repo.github(
    name = "nixpkgs",
    org = "NixOS",
    repo = "nixpkgs",
    commit = "ff0dbd94265ac470dda06a657d5fe49de93b4599",
    sha256 = "1bf0f88ee9181dd993a38d73cb120d0435e8411ea9e95b58475d4426c0948e98",
)
use_repo(nix_repo, "nixpkgs")

non_module_dependencies = use_extension("//:non_module_dependencies.bzl", "non_module_dependencies")
use_repo(non_module_dependencies, "nixpkgs_java_runtime_toolchain")

register_toolchains("@nixpkgs_java_runtime_toolchain//:all")

archive_override(
    module_name = "rules_nixpkgs_java",
    urls = "https://github.com/tweag/rules_nixpkgs/releases/download/v0.12.0/rules_nixpkgs-0.12.0.tar.gz",
    integrity = "",
    strip_prefix = "rules_nixpkgs-0.12.0/toolchains/java",
)

Add the following to a .bzl file, like non_module_dependencies.bzl, to import a JDK from nixpkgs:

load("@rules_nixpkgs_java//:java.bzl", "nixpkgs_java_configure")

def _non_module_dependencies_impl(_ctx):
    nixpkgs_java_configure(
        name = "nixpkgs_java_runtime",
        attribute_path = "openjdk19.home",
        repository = "@nixpkgs",
        toolchain = True,
        toolchain_name = "nixpkgs_java",
        toolchain_version = "19",
        register = False,
    )

non_module_dependencies = module_extension(
    implementation = _non_module_dependencies_impl,
)

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

build --host_platform=@rules_nixpkgs_core//platforms:host
build --java_runtime_version=nixpkgs_java_19
build --tool_java_runtime_version=nixpkgs_java_19
build --java_language_version=19
build --tool_java_language_version=19
build --extra_toolchains=@nixpkgs_java_runtime_toolchain//:all # necessary on NixOS only

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 a Bazel toolchain based on the Java runtime.

register

optional. default is None

Register the created toolchain. Requires toolchain to be True. Defaults to the value of toolchain.

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_local_repository

nixpkgs_local_repository(name, nix_file, nix_file_deps, nix_file_content, nix_flake_lock_file,
                         kwargs)

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.

Parameters

name

required.

String

A unique name for this repository.

nix_file

optional. default is None

Label

A file containing an expression for a Nix derivation.

nix_file_deps

optional. default is None

List of labels

Dependencies of nix_file if any.

nix_file_content

optional. default is None

String

An expression for a Nix derivation.

nix_flake_lock_file

optional. default is None

String

A flake lock file that can be used on the provided nixpkgs repository.

kwargs

optional.

Additional arguments to forward to the underlying repository rule.

nixpkgs_nodejs_configure

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

Parameters

name

optional. default is "nixpkgs_nodejs"

attribute_path

optional. default is "nodejs"

repository

optional. default is None

repositories

optional. default is {}

nix_platform

optional. default is None

nix_file

optional. default is None

nix_file_content

optional. default is None

nix_file_deps

optional. default is None

nixopts

optional. default is []

fail_not_supported

optional. default is True

quiet

optional. default is False

exec_constraints

optional. default is None

target_constraints

optional. default is None

register

optional. default is True

nixpkgs_nodejs_configure_platforms

nixpkgs_nodejs_configure_platforms(name, platforms_mapping, attribute_path, repository,
                                   repositories, nix_platform, nix_file, nix_file_content,
                                   nix_file_deps, nixopts, fail_not_supported, quiet,
                                   exec_constraints, target_constraints, register, kwargs)

Runs nixpkgs_nodejs_configure for each platform.

Since rules_nodejs adds platform suffix to repository name, this can be helpful if one wants to use npm_install and reference js dependencies from npm repo. See the example directory.

Parameters

name

optional. default is "nixpkgs_nodejs"

platforms_mapping

optional. default is {"aarch64-darwin": struct(exec_constraints = ["@platforms//os:macos", "@platforms//cpu:arm64"], rules_nodejs_platform = "darwin_arm64", target_constraints = ["@platforms//os:macos", "@platforms//cpu:arm64"]), "x86_64-linux": struct(exec_constraints = ["@platforms//os:linux", "@platforms//cpu:x86_64"], rules_nodejs_platform = "linux_amd64", target_constraints = ["@platforms//os:linux", "@platforms//cpu:x86_64"]), "x86_64-darwin": struct(exec_constraints = ["@platforms//os:macos", "@platforms//cpu:x86_64"], rules_nodejs_platform = "darwin_amd64", target_constraints = ["@platforms//os:macos", "@platforms//cpu:x86_64"]), "aarch64-linux": struct(exec_constraints = ["@platforms//os:linux", "@platforms//cpu:arm64"], rules_nodejs_platform = "linux_arm64", target_constraints = ["@platforms//os:linux", "@platforms//cpu:arm64"])}

struct describing mapping between nix platform and rules_nodejs bazel platform with target and exec constraints

attribute_path

optional. default is "nodejs"

repository

optional. default is None

repositories

optional. default is {}

nix_platform

optional. default is None

nix_file

optional. default is None

nix_file_content

optional. default is None

nix_file_deps

optional. default is None

nixopts

optional. default is []

fail_not_supported

optional. default is True

quiet

optional. default is False

exec_constraints

optional. default is None

target_constraints

optional. default is None

register

optional. default is True

kwargs

optional.

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 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, .dylib and .a files that can be found in subdirectories of lib/.
:include
All .h, .hh, .hpp and .hxx files that can be found in subdirectories of include/.

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.

Subject to location expansion, any instance of $(location LABEL) will be replaced by the path to the file referenced by LABEL relative to the workspace root.

Note, labels to external workspaces will resolve to paths that contain ~ characters if the Bazel flag --enable_bzlmod is true. Nix does not support ~ characters in path literals at the time of writing, see #7742. Meaning, the result of location expansion may not form a valid Nix path literal. Use ./$${"$(location @for//:example)"} to work around this limitation if you need to pass a path argument via --arg, or pass the resulting path as a string value using --argstr and combine it with an additional --arg workspace_root ./. argument using workspace_root + ("/" + path_str).

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, python3_attribute_path, python3_bin_path, repository, repositories,
                         nix_file_deps, nixopts, fail_not_supported, quiet, exec_constraints,
                         target_constraints, register)

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.

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.

register

optional. default is True

nixpkgs_python_repository

nixpkgs_python_repository(name, repository, repositories, nix_file, nix_file_deps, quiet)

Define a collection of python packages based on a nix file.

The only entry point is a nix_file which should expose a pkgs and a python attributes. python is the python interpreter, and pkgs a set of python packages that will be made available to bazel.

⚠️ All the packages in pkgs are built by this rule. It is therefore not a good idea to expose something as big as pkgs.python3 as provided by nixpkgs.

This rule is instead intended to expose an ad-hoc set of packages for your project, as can be built by poetry2nix, mach-nix, dream2nix or by manually picking the python packages you need from nixpkgs.

The format is generic to support the many ways to generate such packages sets with nixpkgs. See our python tests and examples to get started.

This rule is intended to mimic as closely as possible the rules_python API. nixpkgs_python_repository should be a drop-in replacement of pip_parse. As such, it also provides a requirement function.

⚠️ Using the requirement fucntion inherits the same advantages and limitations as the one in rules_python. All the function does is create a label of the form @{nixpkgs_python_repository_name}//:{package_name}. While depending on such a label directly will work, the layout may change in the future. To be on the safe side, define and import your own requirement function if you need to play with these labels.

⚠️ Just as with rules_python, nothing is done to enforce consistency between the version of python used to generate this repository and the one configured in your toolchain, even if you use nixpkgs_python_toolchain. You should ensure they both use the same python from the same nixpkgs version.

⚠️ packages names exposed by this rule are determined by the pname attribute of the corresponding nix package. These may vary slightly from names used by rules_python. Should this be a problem, you can provide you own requirement function, for example one that lowercases its argument.

Parameters

name

required.

The name for the created package set.

repository

optional. default is None

See nixpkgs_package.

repositories

optional. default is {}

See nixpkgs_package.

nix_file

optional. default is None

See nixpkgs_package.

nix_file_deps

optional. default is []

See nixpkgs_package.

quiet

optional. default is False

See nixpkgs_package.

nixpkgs_rust_configure

nixpkgs_rust_configure(name, default_edition, repository, repositories, nix_file, nix_file_deps,
                       nix_file_content, nixopts, fail_not_supported, quiet, exec_constraints,
                       target_constraints, register)

Parameters

name

optional. default is "nixpkgs_rust"

default_edition

optional. default is "2018"

repository

optional. default is None

repositories

optional. default is {}

nix_file

optional. default is None

nix_file_deps

optional. default is None

nix_file_content

optional. default is None

nixopts

optional. default is []

fail_not_supported

optional. default is True

quiet

optional. default is False

exec_constraints

optional. default is None

target_constraints

optional. default is None

register

optional. default is True

nixpkgs_sh_posix_configure

nixpkgs_sh_posix_configure(name, packages, exec_constraints, register, 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.

exec_constraints

optional. default is None

Constraints for the execution platform.

register

optional. default is True

Automatically register the generated toolchain if set to True.

kwargs

optional.

rules_nixpkgs's People

Contributors

aherrmann avatar aleksandergondek avatar avdv avatar benradf avatar bryanhonof avatar cgrindel avatar cocreature avatar dependabot[bot] avatar evertedsphere avatar facundominguez avatar fricklerhandwerk avatar github-actions[bot] avatar guibou avatar hofbi avatar itsadrake avatar kczulko avatar lamcw avatar layus avatar mboes avatar mergify[bot] avatar nlewo avatar picnoir avatar prednaz avatar profpatsch avatar renovate[bot] avatar rickvanprim avatar tek avatar thufschmitt avatar yoriksar avatar z8v avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rules_nixpkgs's Issues

Incorrect cache behavior for `nixpkgs_package`

nixpkgs_package caching is based on the parameters of the rule, such as nix_file or nix_file_content. They can reference other files which are not taken into account by the cache.

This mean that any change in these files does not invalidate the cache.

Proposed new design (I'll evaluate feasibility soon, bazel needs a way to force a rule to be run and control over the caching mecanism), the rule should always been build, but the caching / invalidation should be based on the result of the underlying nix-build command.

Expose nix-installed binaries in PATH

Currently, there is no way to use nix-installed binaries in (e.g.) shell tests without directly referencing their full path in the script.

For example, we can make something like this to use Redis in a test:

WORKSPACE file:

nixpkgs_package(
  name = "redis",
  repository = "@nixpkgs",
  nix_file_content = """
let nixpkgs = import <nixpkgs> {};
in nixpkgs.buildEnv {
  name = "numero-toolchain";
  paths = [ nixpkgs.redis ];
}
""",
  build_file_content = """
package(default_visibility = ["//visibility:public"])

filegroup(
  name = "bin",
  srcs = glob(["nix/bin/*"]),
)
""",
)

BUILD file:

sh_test(
    name = "my-test",
    size = "small",
    srcs = ["my-test.sh"],
    data = ["@redis//:bin"]
)

my-test.sh file:

#!/usr/bin/env sh

./external/redis/nix/bin/redis-server

But we can"t invoke redis-server directly as it is not in $PATH. This makes the test depend on how Redis is installed, which is not satisfactory.

Rework the hermeticity heuristic

In #82 we discussed the fact that the hermeticity heuristic implemented in nixpkgs_package is too complicated.

The current implementation parses the output of nix-build -vv and tries to detect references to files which are not listed in nix_file_deps. This parsing is fragile and complicated.

@mboes proposed during the #82 discussion to replace this code by a simple copy (symlink) of all the files listed in nix_file_deps in another temporary workspace in which the nix-build will be executed. This solution does not track dependencies on absolute path, but it way simpler.

nixpkgs_local_repository dependency change doesn't invalidate nixpkgs_package

Given a WORKSPACE with something like this:

nixpkgs_local_repository(
    name = "nixpkgs",
    nix_file = "//my/nixpkgs/default.nix",
    nix_file_deps = [ "//my/nixpkgs/something.nix"],
)

nixpkgs_package(
    name = "foo",
    attribute_path = "foo",
    repository = "@nixpkgs",
)

I'd expect that changes to my/nixpkgs/something.nix will force @foo to be rebuilt, but it seems that it doesn't and only changes to my/nixpkgs/default.nix will do. We had some reproducibility issues because of this, our workaround was to merge everything in one big file and avoid nix_file_deps.

From looking quickly through the code, the label "@nixpkgs" corresponds to @nixpkgs//:nixpkgs and this is symlinked to my/nixpkgs/default.nix, so iiuc, from the point of view of bazel, @foo only depends on that file, and not on my/nixpkgs/something.nix. I guess @nixpkgs//:nixpkgs could instead be defined to be a filegroup() containing the given nix_file and everything in nix_file_deps?

Remove `nixpkgs_git_repository`, it clashes with nix_file_deps heuristics

A minimal WORKSPACE setup of rules_haskell that uses nixpkgs_git_repository fails on current master because nixpkgs_git_repository checks out nixpkgs into a bazel repository, which makes the heuristic require to manually specify every single file from the checked out nixpkgs. See this discission.

@guibou says:

You can imagine a even more minimal setup such as:

haskell_register_ghc_nixpkgs(
   version = "8.4.3",
   repositories = { "nixpkgs": ":nixpkgs.nix" }
)

Where nixpkgs.nix contains the relevant fetchTarball call. This solution does not use nixpkgs_git_repository and is more reproducible. Actually, I just realized that nixpkgs_git_repository does not forces the usage of the sha256 argument and hence is not reproducible.

So the best plan of action we figured out is to ask the user to use the nix-based fetchTarball approach and remove nixpkgs_git_repository.

cc @regnat @mboes

Add a `nixpkgs_packageset` rule

Since tweag/rules_haskell#442, the evaluation of the workspace of a rules_haskell-enabled repository takes an insane amount of time because it requires nix-build-ing every transitive haskell dependency, which easily means more than 200 nix-build calls.
We could speed things a lot by first nix-instantiate-ing a big json file mapping each haskell package to its .drv, and then just realize as needed these pre-intstantiated derivations. This would avoid the cost of evaluating nixpkgs 200 times (which is by far the bottleneck when everything is already built).

This trick can probably be used for more than just the haskellPackages case, so I propose we add a nixpkgs_packages_set rule to rules_nixpkgs which would be used like:

nixpkgs_packages_set(
  name = "haskellPackages",
  repository = "@nixpkgs",
  base_attribute_path = "haskellPackages",
)

This would generate @haskellPackages-base, @haskellPackages-streaming,
@haskellPackages-foobar, … (and possibly one @haskellPackages with aliases
in it for all of these.

Internally this rule would

  1. nix-instantiate a json file of the form

    {
      "base": "/nix/store/…-base.drv",
      "streaming": "/nix/store/…-streaming.drv",
      "foobar": "/nix/store/…-foobar.drv",
      
    }
  2. Load this into a starlark dict one way or another

  3. For each element of this dict, generate a call to a rule which would nix-store --realize the corresponding derivation

All this would require extending a bit the scope of nixpkgs (or doing thing in an ad-hoc way, not sure what's the best choice), to add

  • A nix_instantiate rule allowing to import the result of nix-instantiate
  • A nix_realize rule which would wrap nix-store --realize

Thoughs?

Support expressing a derivation in a .nix file

We can currently select a derivation using an attribute path. #4 proposes to allow arbritrary expressions. Should add an extra field to nixpkgs_package rule called nix_file, containing an expression for a derivation. The attr_path field, if specified, can then be interpreted as selecting an attribute within the derivation.

"setitimer": Invalid argument

Updating from Bazel 0.28.1 to 1.1.0 I observed the following error with rules_nixpkgs on macOS:

ERROR: An error occurred during the fetch of repository 'node_nix':
   Traceback (most recent call last):
        File "/private/var/tmp/_bazel_runner/17d2b3954f1c6dcf5414d5453467df9a/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 149
                _execute_or_fail(repository_ctx, <3 more arguments>)
        File "/private/var/tmp/_bazel_runner/17d2b3954f1c6dcf5414d5453467df9a/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 318, in _execute_or_fail
                fail(<1 more arguments>)

Cannot build Nix attribute 'nodejs'.
Command: [/Users/runner/.nix-profile/bin/nix-build, /private/var/tmp/_bazel_runner/17d2b3954f1c6dcf5414d5453467df9a/external/node_nix/nix/bazel.nix, "-A", "nodejs", "--out-link", "bazel-support/nix-out-link", "-I", "nixpkgs=/private/var/tmp/_bazel_runner/17d2b3954f1c6dcf5414d5453467df9a/external/nixpkgs/nixpkgs"]
Return code: 1
Error output:
src/main/tools/process-tools.cc:173: "setitimer": Invalid argument

The problem seems to be caused by a too large timeout value passed to repository_ctx.execute. Changing the value from 1073741824 (2^30) to 8640000 (100 days) seems to solve this issue.

This commit seems to be the relevant change to Bazel. The call to setitimer in process-tools.cc is here and was last changed in 2017.

For reference, the macOS manpage for setitimer states

ERRORS
     Getitimer() and setitimer() will fail if:

     [EFAULT]           The value parameter specified a bad address.

     [EINVAL]           The value parameter specified a time that was too
                        large to be handled or not in the canonical form.

     [EINVAL]           The which parameter was invalid.

nixpkgs_local_repository nix_file_deps is mangled

I have

nixpkgs_local_repository(
    name = "nixpkgs",
    nix_file = "//nix:nixpkgs.nix",
    nix_file_deps = [
        "//nix:fetch.nix",
    ],

which seems to end up in the bazel cache as:

$ ls ...../external/nixpkgs
BUILD  nixpkgs  nixpkgs.nix  nix_Sfetch.nix  WORKSPACE

Regression: short form repository labels don't work anymore

It used to be possible to write this:

nixpkgs_package(
  name = "foo",
  repository = "@nixpkgs",
)

This is a lot shorter than repositories = {"nixpkgs": "@nixpkgs//:default.nix"}. The reason this worked before is that we had a symlink that had the same name as the repository, pointing to default.nix, since @foo is actually syntactic sugar for @foo//:foo in Bazel.

It would be nice to have this shorthand available again. Incidentally, I think we should not deprecate repository, even though repositories now exists.

How to use rules_nixpkgs for python packages

Hi repo owners & @mboes,

I'm from the remote build execution team at Google and we are evaluating nix as a hermetic package manager for remote builds. I'm trying to create a project that uses rules_nixpkgs to download the flask python package and use it in a python hello world server app.

I created https://github.com/smukherj1/eval_nixpkgs. This project has a Dockerfile that creates a container with bazel and the nix package manager. I have a script "docker_run.sh" which takes a single argument which should be the name of the image created by the Dockerfile. Note that this script needs to be in your current directory when you execute it. The script tries to build the python app using bazel in a docker container.

Currently, I get the following error:-
ERROR: Analysis of target '//:app' failed; build aborted: no such package '@python2.7-Flask-1.0.2//': Traceback (most recent call last): File "/root/.cache/bazel/_bazel_root/ec321eb2cc2d0f8f91b676b6d4c66c29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 82 ":".join([((path_name + "=") + str(ctx.pa...()]) File "/root/.cache/bazel/_bazel_root/ec321eb2cc2d0f8f91b676b6d4c66c29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 83, in ":".join str(ctx.path(target)) File "/root/.cache/bazel/_bazel_root/ec321eb2cc2d0f8f91b676b6d4c66c29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 83, in str ctx.path(target) Not a regular file: /workdir/external/nixpkgs

Now this is almost certainly because I created the bazel project wrong. Any guidance on where I went wrong would be greatly appreciated!

Thanks in advance for your help :)

Document the trick to directly reference nix files in repositories

A very handy trick is to say

nixpkgs.nix

import (fetchTarball { … nixpkgs repository url & hash … })

and then use

nixpkgs_package(
  repositories = { "nixpkgs": "//:nixpkgs.nix" }
  …
)

in the WORKSPACE file to refer to a pinned nixpkgs. repositories is directly translated into entries in the NIX_PATH environment variable and thus picked up inside nix files as the variable <packageName> (<nixpkgs> in this case).

Verbosity of nixpkgs_package

Current nixpkgs_package is quiet during package installation. It can be mute as such for a really long time if the nix process is long, giving no user feedback. In case of error, it shows a highly verbose nix output which is totally unusable for the user.

This changes are due to #77, in which removed the verbosity of nixpkgs_package. This was mostly due to #76 which introduced an heuristic for better reproducibility, but this heuristic is using the highly verbose output of nixpkgs_package that user do not want to see.

I propose to implement two changes:

  • The underlying nix-build process will be run twice. Once with nix normal verbosity and the second time with the highest verbosity.
  • A quiet option will be added to nixpkgs_package (and associated rules). It default to True, but when switched to False it will display the progress of the nix-build command, using the normal output.

The heuristic will be computed using the output of the second run. This way, if first run fails, or quiet is set to False, user will see an informative output. The second run should never fail.

This will introduce a bit of overhead because nix-build will be called twice.

Alternative solutions

  • split the build between nix-instanciate and nix-build and only run the heuristic (hence verbose output) on the nix-instanciate call, and setting the quiet flag on the nix-build call. This will be an improvement in case of error during the nix-build phase, however if any error occur during the nix-instanciate phase, user will still face a long and verbose output.

Should I implement that?

Random index of range error

Describe the bug

Since I upgraded rules_nixpkgs from rules_nixpkgs-0.3.1 to 67a80de8648b2b40a3b7f5b4b8b7f2ad95c1a08c we are experiencing random and weird issues with some bazel calls fails such as:

$ bazel build //...
INFO: Invocation ID: 7a93f2ef-0897-4ad2-b6ac-4171ccd78dd2
ERROR: /my/workspace/BUILD.bazel:13:1: no such package '@foo//': index out of range (index is 1, but sequence has 1 elements) and referenced by '//:bar'
ERROR: Analysis of target '//rat/crevette:chien' failed; build aborted: no such package '@foo//': index out of range (index is 1, but sequence has 1 elements)
INFO: Elapsed time: 10.505s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (12 packages loaded, 51 targets configured)
FAILED: Build did NOT complete successfully (12 packages loaded, 51 targets configured)

The build succeed if the command is ran another time. No bazel clean was necessary.

To Reproduce

I'm unable to consistently reproduce the issue. Initially I was tempted to think that it was something wrong in an internal state after the upgrade and that running bazel fixed it, but it appears to come back sometimes. I don't know what triggers it. I can do a full bisect on the codebase jumping around the rules_nixpkgs upgrade and not observe the issue, but I can also observe it sometimes after minors changes in my sources.

Expected behavior

I don't want unpredictable failures. Actually that's not a dramatic issue to work (we just need to run bazel again), but it makes continuous integration difficult because it may randomly fail.

Environment

  • Linux, happened on different flavors of nixos or ubuntu
  • Bazel 0.22 from nixpkgs
  • Version of the rules: 67a80de

Additional context

I'm opening the issue for tracking. If nobody have the same issue, I'll conclude as an issue specific from our setup.

Consider exposing all files in a filegroup

Currently we only expose .so files from lib and things from bin: this is quite restrictive: we can't use header files or use binaries that don't live directly in bin &c.

Is there any good reason to not have an out file group that user can reach for?

Related question: can use filter filegroups? That'd be very useful.

nixpkgs_package shouldn't default to <nixpkgs>

When calling nixpkgs_package without any of the path or repository argument, bazel complains:

DEBUG: /home/guillaume/.cache/bazel/_bazel_guillaume/9923957c70cd7b59bec21e32af97c8be/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl:66:5: 
WARNING: Implicitly using '<nixpkgs>' as the location of Nixpkgs.
This is not recommended because it makes the build non-hermetic.
Set which Nixpkgs to use explicitly using 'repository' or 'path' attributes.

My setup is correct and hermetic because the file pointed by nix_file setups its own pinned clone of nixpkgs. To remove the warning, I have to set a dummy path = ".".

I propose the following changes:

  • remove the defaulting to <nixpkgs> when neither path nor repository are selected. and instead load the provided nix_file (or nix_file_content) with no value for <nixpkgs>.
  • (optional) add a new attribute enable_impure_nixpkgs_source, with default to false, which re-enable the current behavior.

This way, by default, the user MUST provides either path or repository or a nix_file with a pinned nixpkgs. The optional new attribute may allow her to get back the unsafe behavior.

I'm opening the issue for discussion, PR will follow if we agree on the design.

This may be a good final conclusion to #17

Why is `nixpkgs_package` marked as `local`

The nixpkgs_package rule has local = True, which means that it will be re-executed each time something changes anywhere in the workspace.
This is very costly since evaluating them can take a long time and they should be pure.
Is there any reason for this?

According to git blame, it has been introduced as part of 4b63a7e.

/cc @mboes

Replace nixpkgs_cc_configure() with a toolchain

CC rules have experimental support for using toolchains, rather than a single repository at a known location: bazelbuild/bazel#7260. We should replace nixpkgs_cc_configure() with a toolchain, that can be selected through Bazel's regular constraint mechanism. We can have a Nixpkgs specific constraint setting, which users can set in order to select this toolchain.

A problem with nixpkgs_cc_configure() currently is that it silently fails when Nix is not available. This is desirable for systems that don't have Nix, but it also means that the rule will silently alter the active CC toolchain depending on whether the Nix tools are on the path or not. This leads to user confusion, as we saw in tweag/rules_haskell#704. Using toolchains instead should avoid this problem.

Can nixpkgs_package generate better BUILD files?

The current build template, nixpkgs/BUILD.pkg, is pretty bare bones. I imagine most users have a series of macros to provide a build_file or build_file_content.

Is it possible to add cc_library / py_library and other targets to the default template, or ask nix for the information needed to conditionally create those targets?

Also, what languages are well supported by rules_nixpkgs (and nixpkgs)? I see most of the examples in this repo are haskell, but I assume that any language that provides a package per library (c, python, haskell) work well with bazel, and those that aren't packaged similarly do not (rust, java).

Use Niv to fetch nixpkgs

Instead of the custom nixpkgs.json and nixpkgs.nix files, we could use Niv to generate such files. This would allow use to update the nixpkgs revision/hash with a single command (niv update nixpkgs).

nixpkgs_package dependency change does not invalidate repository

This is a new variation of #17

nixpkgs_package allows users to list the nix dependencies using nix_file_deps, but that's of no help for reproducibility because nixpkgs_package will work even if the nix process depends on files not listed in nix_file_deps.

For example, the following won't be invalidated in case foo.nix dependencies change.

nixpkgs_package(
    name = "foo",
    attribute_path = "foo",
    repositories = {"nixpkgs": "//:foo.nix"},
)

Provide toolchain for rules_go and rules_node

Hello,

Can this be used to provide binaries required by rules_go and rules_nodejs?

Go toolchain can be configured as explained here.

NodeJS is a bit more complex, so far I got it to work by doing the following:

node_repositories(
    package_json = [
        "//rules_nodejs:package.json",
    ],

    node_path = "/nix/store/q05xbja14rsgqzknmmlkajnzacjnp4hl-nodejs-8.11.3",
    yarn_path = "/nix/store/fc9n30kjp7q04s520w4n34c3rbhsqdnl-yarn-1.8.0/libexec/yarn",
)

which means that I somehow need to get the location of @nodejs//:bin/node. Is this possible?

See full example here

Verbose option for nixpkgs_package

nixpkgs_package is not verbose at all and sometimes users can observe a bazel process stuck on fetching @some_package because the underlying nix process takes time. See #82 for a more detailled discussion.

In #82 I proposed to introduce a new attribute to nixpkgs_package, quiet. This attributes copies the behavior of the similarly named parameter of the repository_ctx.execute function: True by default, meaning no output (the current behavior), but can be switched False by the user, meaning that the output of the underlying subprocess is copied verbatim to bazel outputs.

In this issue, I propose that we implement this attribute.

Note that we cannot just switch back to quiet = False by default because it will leaks nix output to bazel output in all cases, which may break scripts using, for example, bazel query.

This work is blocked by the resolution of #84 because for now nix-build is too verbose.

nix-build progress is suppressed

When using nixpkgs_package, the user is just sitting there waiting while package builds. Would be nicer if we could see the output so that we both know the progress and can see the errors if something goes wrong.

nixpkgs_package does not invalidate when a file not listed in nix_file_deps changes

Describe the bug

nix_file_deps tracks the list of file which must trigger a cache invalidation of nixpkgs_package when they change.

However, if a file is not listed in this list, bazel will still build the nixpkgs_package, but later changes to this

To Reproduce

git checkout 65b47e980fb9bfb05c1dff9c2229a77b7d891541
cd repro
nix-shell -A repro
# observe the value
# change the value in inc.nix
nix-shell -A repro
# observe that the value did not change
nix-shell -A clean
nix-shell -A repro
# observe that the value did change after a clean

Expected behavior

I'd like the change to be taken into account without the need to bazel clean --expunge. Note that adding the necessary files (i.e. default.nix and inc.nix) to nix_file_deps does the job of invalidating the build. However #74 was supposed to trigger an error if a mandatory file was not in nix_file_deps.

Environment

  • OS name + version: linux nixos something
  • Version of the code: see the associated changeset: 65b47e9

New nix-specific configuration setting

Is your feature request related to a problem? Please describe.

Platforms use the //nixpkgs/constraints:nixpkgs constraint value to indicate that they support Nix. However, this constraint value is both poorly named and poorly designed. It's poorly named because we don't care about Nixpkgs support per se, we care about whether Nix is available on the system or not. It's poorly designed because it's a value of the @bazel_tools//tools/cpp:cc_compiler constraint setting, which is an abuse of that setting. Platforms can only set one constraint value for any given constraint setting, yet we'd want to set a C/C++ compiler constraint value independently of whether it comes from Nixpkgs or not.

Describe the solution you'd like

Define a new constraint setting, called nix, with one constraint value, called support_nix. This is the pattern used in https://github.com/bazelbuild/bazel-toolchains, e.g. for sanitizer support or Docker support.

Describe alternatives you've considered

An alternative would be to ask upstream to define a generic package_manager constraint setting, with nixpkgs being a constraint value. I ask for precisely this in bazelbuild/platforms#5. Apart from the fact that it has proved to avoid the discussion there from stalling, I think that in the end doing differently may be better anyways. Multiple package managers should be able to coexist. Defining a new constraint_setting rather than using a generic one is simpler, works for now, and there isn't much to be gained from defining a unique slot for all package tools like Flatpak, Snappy, Nix etc.

Not enough GC roots created to prevent nix gc from removing stuff

after a nix-store --gc:

INFO: Call stack for the definition of repository 'stackage' which is a _stack_snapshot (rule definition at /home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl:970:19):
 - /home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl:1184:5
 - /home/philip/kot/work/tweag/someproject/WORKSPACE:128:1
ERROR: An error occurred during the fetch of repository 'stackage':
   Traceback (most recent call last):
	File "/home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl", line 865
		_compute_dependency_graph(<6 more arguments>)
	File "/home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl", line 713, in _compute_dependency_graph
		repository_ctx.path(<1 more arguments>)
Not a regular file: /home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell_stack/stack
ERROR: /home/philip/kot/work/tweag/someproject/backend/tests/api-tests/BUILD.bazel:7:1: //backend/tests/api-tests:api-tests depends on @stackage//:base in repository @stackage which failed to fetch. no such package '@stackage//': Traceback (most recent call last):
	File "/home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl", line 865
		_compute_dependency_graph(<6 more arguments>)
	File "/home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl", line 713, in _compute_dependency_graph
		repository_ctx.path(<1 more arguments>)
Not a regular file: /home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell_stack/stack
ERROR: /home/philip/kot/work/tweag/someproject/backend/tests/api-tests/BUILD.bazel:7:1: //backend/tests/api-tests:api-tests depends on @stackage//:bytestring in repository @stackage which failed to fetch. no such package '@stackage//': Traceback (most recent call last):
	File "/home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl", line 865
		_compute_dependency_graph(<6 more arguments>)
	File "/home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell/haskell/cabal.bzl", line 713, in _compute_dependency_graph
		repository_ctx.path(<1 more arguments>)
Not a regular file: /home/philip/.cache/bazel/_bazel_philip/ec4bffc753a4896ad5f0595f4cbba0c3/external/rules_haskell_stack/stack

and so on

We must be missing some GC roots.

> bazel version
Another command (pid=3664) is running.  Waiting for it to complete on the server...
Build label: 2.0.0- (@non-git)
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Tue Jan 1 00:00:00 1980 (315532800)
Build timestamp: 315532800
Build timestamp as int: 315532800
http_archive(
    name = "rules_haskell",
    strip_prefix = "rules_haskell-1150e2158fc21a365920a4a42a3aa6f79cdf49c3",
    # rules_haskell master 2020-01-30
    urls = ["https://github.com/tweag/rules_haskell/archive/1150e2158fc21a365920a4a42a3aa6f79cdf49c3.tar.gz"],
    sha256 = "1bbd30c24434a7272da77c664bd4b01083cd412cd0b6ad511ed9247bb6d2f55a",
)

which according to
https://github.com/tweag/rules_haskell/blob/1150e2158fc21a365920a4a42a3aa6f79cdf49c3/haskell/repositories.bzl#L51-L57
is rules_nixpkgs 0.6.0

TODO: create repro

toolchain doesn't get rebuilt

We seem to be hitting a situation where the bazel CC toolchain isn't being rebuilt.
This manifests itself as the following error during compilation:

ERROR: /private/var/tmp/_bazel_hydra/633f952cd27cedaca2fec002b6ff9981/external/haskell_primitive__1834808089/BUILD:15:1: undeclared inclusion(s) in rule '@haskell_primitive__1834808089//:primitive-cbits':
this rule is missing dependency declarations for the following files included by 'external/haskell_primitive__1834808089/cbits/primitive-memops.c':
  '/nix/store/ab8m18ziqfcj86229gwjlzbpgfdf1f39-libc++-5.0.2/include/c++/v1/string.h'
  '/nix/store/ab8m18ziqfcj86229gwjlzbpgfdf1f39-libc++-5.0.2/include/c++/v1/__config'

When inspecting the "CROSSTOOL" file one sees that the include paths are out of date:

$ grep libc++ $(bazel info output_base)/external/local_config_cc/CROSSTOOL
  cxx_builtin_include_directory: "/nix/store/wi7la300b1j34sklv64p4ap09zyzzngv-libc++-5.0.2/include/c++/v1"

I've tried different combinations of flags to nixpkgs_cc_configure and while I can trigger it to
do a nix-build of e.g. the nix-file specifying the tools it does not appear to have an impact on
CROSSTOOL itself. There is also no mention of the nix files as dependencies for @local_config_cc, which might explain it (bazel query 'deps(@local_config_cc//...)').

Platform autodetection

Since there is currently no support for custom platform/constraint autodetection/autodiscovery (see bazelbuild/bazel#8766) there is no way sane way to use neither nixpkgs_python_configure nor nixpkgs_sh_posix_configure and they just being autodetected by bazel itself from existing environment and not from nixpkgs (at least until no --platforms and host_platform equal to @io_tweag_rules_nixpkgs//constraints:linux_x86_64_nixpkgs specified manually)

So should we just drop that constraints from toolchains?

Pros:

  • fully hermetic nix-driven builds with zero fuss
  • as I can understand from documentation to toolchains and constraints/platforms it wasn't meant to be used in toolchains like this anyway (but probably we whould wrap nix itself in toolchain and provide it under constraint - that would make sense, but not until bazel figures out how to automatically provide values for constraints based on some user code)

Cons:

  • currently calling those _configure ultimately does nothing, so we may break something with that change (do we really care? especially if it is called directly and MEANT to do so?)
  • from the doc it is not clear if those _configure are public api of this rules or not, so probably this issue is for nothing (we should write some doc probably)

[request] nixpkgs_python_configure support for 'quiet' attribute

Is your feature request related to a problem? Please describe.

In 0.7.0 we got support for quiet attribute on nixpkgs_package. It's a nice feature, but when using nixpkgs_python_configure it's hidden from the user.

Describe the solution you'd like

Access to this attribute from nixpkgs_python_configure

Additional context

Would you accept a PR?

More explicit 'Platform is not supported' message?

While using rules_nixpkgs for rules_haskell, I did the following:

> mkdir -p test/nested
> cd test
> git clone https://github.com/tweag/rules_haskell
> cd nested
> ./../rules_haskell/start --use-nix # Create rules_haskell standard template
> nix-shell --pure -p bazel
> bazel build //... # Try to build the template
Starting local Bazel server and connecting to it...
ERROR: An error occurred during the fetch of repository 'rules_haskell_sh_posix_nixpkgs':
   Platform is not supported (see 'fail_not_supported')
ERROR: /media/crypt1/repos/test/nested/BUILD.bazel:29:1: //:example depends on @rules_haskell_sh_posix_nixpkgs//:nixpkgs_sh_posix in repository @rules_haskell_sh_posix_nixpkgs which failed to fetch. no such package '@rules_haskell_sh_posix_nixpkgs//': Platform is not supported (see 'fail_not_supported')
ERROR: Analysis of target '//:example' failed; build aborted: no such package '@rules_haskell_sh_posix_nixpkgs//': Platform is not supported (see 'fail_not_supported')
INFO: Elapsed time: 15.039s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (17 packages loaded, 26 targets configured)
    Fetching @rules_haskell_ghc_nixpkgs_haskell_toolchain; Restarting. 12s

which is indeed to be expected, because I ran a --pure shell with only bazel (so no nix* on the $PATH).

I was however, puzzled by the Platform is not supported message; would it make sense to make explicit that nix-build was not found? (as it is what the implementation does: https://github.com/tweag/rules_nixpkgs/blob/master/nixpkgs/nixpkgs.bzl#L59-L60). I can write the patch, but wanted to make sure this is a desirable change beforehand.

Think about garbage collection

rules_nixpkgs has a fundamental problem: neither it nor its users know when the built targets may go away.

Nothing is stopping nix GC running while bazel build is on-going and any tooling removed. This is not a problem for something like stack --nix which uses a nix-shell which prevents the targets from being destroyed. We do not have that luxury with bazel.

However having said that, maybe we don't actually care. nix GC is no different than user removing something from /usr/bin through their package manager for example. We can take the same stance.

On the other hand, bazel itself does things a little bit differently: the tools that it has will usually be downloaded and stored by it: that makes them "guaranteed" to be present modulo malicious intent. The fundamental difference is that one is managed by bazel and the other by nix.

If we can't find a good, reliable solution that lets us keep targets that are in-use (for example by creating GC roots to everything in bazel's external/: this is possible but likely not viable to automate so that it's invisible from the user), we should at least document this drawback.

How to use nixpkgs_cc_configure?

I am seeing this error:

ERROR: in target '//external:cc_toolchain': no such package '@local_config_cc//': no such package '@nixpkgs_cc_toolchain//': Traceback (most recent call last):
        File "/home/preston/.cache/bazel/_bazel_preston/2bf51e8690558a83a0a0514ab422fd4b/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 122
                _executable_path(repository_ctx, "nix-build", extra_m...")
        File "/home/preston/.cache/bazel/_bazel_preston/2bf51e8690558a83a0a0514ab422fd4b/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl", line 325, in _executable_path
                fail("Could not find the `{}` executa... ""))
Could not find the `nix-build` executable in PATH. See: https://nixos.org/nix/
INFO: Elapsed time: 0.258s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (1 packages loaded)
FAILED: Build did NOT complete successfully (1 packages loaded)

My workspace looks something like this:

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

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

nixpkgs_git_repository(
    name = "nixpkgs",
    revision = "17.09",  # Any tag or commit hash
    sha256 = "",  # optional sha to verify package integrity! (yes, I will after I can get it to work...)
)

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

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

...

What am I missing to use nixpkgs_cc_configure?
My goal here is to have more hermetic builds by not relying on the system gcc (inspired by @mboes lightning talk at Bazelcon 2018).

More info:

bazel version
INFO: Invocation ID: fdb8124e-372e-43b0-a8e7-495d445988aa
Build label: 0.20.0
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Fri Nov 30 14:39:01 2018 (1543588741)
Build timestamp: 1543588741
Build timestamp as int: 1543588741

Is nixpkgs_git_repository@revision required?

For nixpkgs_git_repository, the attribute revision is marked as String; optional in the readme but it looks to be required.

In the WORKSPACE file, for nixpkgs_git_repository set only name, the only required attribute;

nixpkgs_git_repository(
    name = "nixpkgs",
)

With that, the build cannot download nixpkgs;

> bazel build //...
...
no such package '@ghc//':
no such package '@nixpkgs//':
java.io.IOException: Error downloading [https://github.com/NixOS/nixpkgs/archive/.tar.gz]

Here's where the URL is constructed;

url = "%s/archive/%s.tar.gz" % (ctx.attr.remote, ctx.attr.revision),

The relevant section of the readme;

https://github.com/tweag/rules_nixpkgs/blame/master/README.md#L70-L75

More reproducibility: fetching nix as part of the rules

Currently, these rules assume the existence of nix-build on the path. It would be nice to declare nix-build as either something bazel can build (which will probably be hard unless it has some nice bootstrapping already) or as binary files with hashes we can use on each platform.

With this, users don't need to install anything to use these rules, which is a bit nice.

How to use nixpkgs_package-based binary as a tool dependency?

I try to source a nixpkgs_package and use it as a tool in a genrule. I couldn't find doc about this, but I found (correctly?) that a nixpkgs_package named foo gets bound to the target //external:foo. So I try to directly build from bazel command-line such package (ghc in the example), or depend on one in a rule (hello in the example). But I get errors about non-visibility of some nix expressions.

This is odd, since ghc is surely picked up by rules_haskell as it works. But maybe Skylark code has different visibility restrictions? Not sure.

I didn't try adding the exports to the BUILD files as suggested by the warnings, since I don't know if this is a red herring. You likely have a better guess. It's also possible I'm doing something silly.

WORKSPACE:

workspace(name = "treetide")

# stripped rules_haskell stuff

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

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

nixpkgs_git_repository(
  name = "nixpkgs",
  revision = "6a3f5bcb061e1822f50e299f5616a0731636e4e7", # "18.09"
)

nixpkgs_package(
  name = "ghc",
  repositories = { "nixpkgs": "@nixpkgs//:default.nix" },
  nix_file = "//:ghc.nix",
  build_file = "@io_tweag_rules_haskell//haskell:ghc.BUILD",
)

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

BUILD:

genrule(
  name = "hi",
  tools = ["//external:hello"],
  outs = ["hi.txt"],
  cmd = "$(location //external:hello) > $@",
)

Failure when trying to access ghc.

 $ bazel build //external:ghc
Starting local Bazel server and connecting to it...
ERROR: ...29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl:136:5:
   no such target '//:ghc.nix': target 'ghc.nix' not declared in package '';
   however, a source file of this name exists. 
   (Perhaps add 'exports_files(["ghc.nix"])' to /BUILD?)
   
ERROR: ...29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl:136:5:
    no such target '@nixpkgs//:default.nix': target 'default.nix' not declared in package '';
    however, a source file of this name exists. 
   (Perhaps add 'exports_files(["default.nix"])' to /BUILD?)
   
ERROR: ...29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl:136:5:
   no such target '@io_tweag_rules_haskell//haskell:ghc.BUILD': target 'ghc.BUILD' not declared in package 'haskell';
   however, a source file of this name exists. 
   (Perhaps add 'exports_files(["ghc.BUILD"])' to haskell/BUILD?)

ERROR: Analysis of target '//external:ghc' failed; build aborted: Analysis failed

Trying on just hello:

 $ bazel build :hi
ERROR: ..29/external/io_tweag_rules_nixpkgs/nixpkgs/nixpkgs.bzl:177:9: no such target '@nixpkgs//:default.nix': target 'default.nix' not declared in package ''; however, a source file of this name exists.  (Perhaps add 'exports_files(["default.nix"])' to /BUILD?) defined by /home/ron/.cache/bazel/_bazel_ron/dea833c6b6c799258fdcca8ca5a2e429/external/nixpkgs/BUILD and referenced by '//external:hello'
ERROR: Analysis of target '//:hi' failed; build aborted: Analysis failed

Edit: in context of NixOS/nixpkgs#50765, wanting to add bazel tools from nix.

Importing a single file with `nixpkgs_package` gives confusing errors

By mistake I tried to use nixpkgs_package on a nix package which output is a single file, such as:

nixpkgs_package(
    name = "output-derivation-is-a-file",
    attribute_path = "",
    nix_file_content = """let pkgs = import <nixpkgs> { config = {}; overlays = []; }; in pkgs.writeText "foo" "bar" """,
    nix_file_deps = [
        "//:nixpkgs.json",
        "//:nixpkgs.nix",
        "//tests:relative_imports/nixpkgs.nix",
    ],
    repository = "@nixpkgs",
)

The error message is confusing:

$ bazel build @output-derivation-is-a-file//...
INFO: Writing tracer profile to '/home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/command.profile.gz'
INFO: Call stack for the definition of repository 'output-derivation-is-a-file' which is a _nixpkgs_package (rule definition at /home/guillaume/tweag/rules_nixpkgs/nixpkgs/nixpkgs.bzl:169:20):
 - /home/guillaume/tweag/rules_nixpkgs/nixpkgs/nixpkgs.bzl:202:9
 - /home/guillaume/tweag/rules_nixpkgs/WORKSPACE:119:1
ERROR: An error occurred during the fetch of repository 'output-derivation-is-a-file':
   java.io.IOException: Could not create symlink from /home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/external/output-derivation-is-a-file to /home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/external/output-derivation-is-a-file: /home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/external/output-derivation-is-a-file (File exists)
ERROR: java.io.IOException: Could not create symlink from /home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/external/output-derivation-is-a-file to /home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/external/output-derivation-is-a-file: /home/guillaume/.cache/bazel/_bazel_guillaume/494c5fef8cb6c9d27d36fadb3784eaa6/external/output-derivation-is-a-file (File exists)
INFO: Elapsed time: 1.658s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (0 packages loaded)

I'd like to be able to import single file like that, but I don't really know how this may fit the bazel paradigm.

However, I think the error message may be more explicit. What do you think? Should I open a PR which checks if the output of the nix derivation is a directory and fail otherwise?

Make a platform switch to assume packages are already built

Currently, when getting packages with rules_nixpkgs, bazel will call nix to build said dependencies.

It doesn't work well, however, when making a nix derivation to package our bazel-built software.

There, we expect that the nix derivation will describe all of the dependencies for the package, and that they will be built by the time bazel starts running.

Here is a thought: we may make a toolchain which, instead of building the dependencies, assume that they are built already. And make it so that a platform argument switches between the two modes. So that a build, driven from nix, will simply pass a command line argument, and won't try to build the dependencies anymore. While building the project, for a developer, will still be only a matter of bazel build.

Now, I'm not sure it is a good idea, for one thing, it requires that the version of nixpkgs used by the Bazel build is the same as the version of nixpkgs assumed by Bazel. Would it even work to package Bazel project within nixpkgs?

What does everybody think?

Is `buildBazelPackage` from nixpkgs supposed to work?

When I try, I get:

ERROR: /tmp/nix-build-foobar.drv-0/source/BUILD:8:1: no such package '@ghc//': Platform is not supported (see 'fail_not_supported') and referenced by '//:ghc-impl'

This is not much error to help troubleshooting, but asking first to see if you attempted and succeeded already.

rules_nixpkgs interacts badly with cc_import on Linux

Trying to execute a cc_binary that depends on a cc_import based on a nixpkgs_package is likely to fail due to missing files in Bazel's generated _solib directory.

Consider the following example. (Provided in full detail in 22fbc2f.)

First, we import libz.so from nixpkgs:

nixpkgs_package(
    name = "zlib",
    repository = "@nixpkgs",
)

Then, we use cc_import to import the shared object:

cc_import(
    name = "z-lib",
    shared_library = "@zlib//:lib/libz.so",
)

Finally, we define a cc_binary (or cc_test) that depends on the library:

cc_binary(
    name = "cc-import-test",
    srcs = ["cc-import-test.cc"],
    deps = [":z-lib"],
)

If we try to execute that binary on Linux (bazel test //tests:cc-import-test on 22fbc2f) it will fail with the following dynamic linking error:

libz.so.1: cannot open shared object file: No such file or directory

The reason is that the generated binary will refer to the library under its soname libz.so.1, but the RUNPATH will only contain the symbolic link libz.so which points to the soname version.

$ readelf -d bazel-bin/tests/cc-import-test
...
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
...
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/../_solib_k8/_U_S_Stests_Cz-lib___Uexternal_Szlib_Slib:...]
...
$ ls bazel-out/k8-fastbuild/bin/tests/cc-import-test.runfiles/io_tweag_rules_nixpkgs/_solib_k8/_U_S_Stests_Cz-lib___Uexternal_Szlib_Slib/
libz.so

A work-around is to use cc_library instead of cc_import and pass all names of the shared object into the srcs attribute:

cc_library(
    name = "z-workaround",
    srcs = ["@zlib//:lib"],
)

The resulting binary (bazel test //tests:cc-import-workaround on 22fbc2f) will still refer to libz.so.1, but the corresponding _solib directory will contain that file:

$ readelf -d bazel-bin/tests/cc-import-workaround
...
 0x0000000000000001 (NEEDED)             Shared library: [libz.so.1]
...
 0x000000000000001d (RUNPATH)            Library runpath: [$ORIGIN/../_solib_k8/_U_S_Stests_Cz-workaround___Uexternal_Szlib_Slib:...]
...
$ ls bazel-bin/tests/cc-import-workaround.runfiles/io_tweag_rules_nixpkgs/_solib_k8/_U_S_Stests_Cz-workaround___Uexternal_Szlib_Slib/
libz.so  libz.so.1  libz.so.1.2.11

This begs the question: Why not always use cc_library instead of cc_import? cc_library resolves the soname issue described above, and also resolves the strip_include_prefix issue as pointed out here.

nixpkgs_package's nix_file attribute appears to be broken

I'm looking to use nixpkgs_package along with a local nix file, contained within the same Git repository. This is to remove a large amount of Nix out of the WORKSPACE file and in to a properly named and syntax highlighted .nix file.

From what I've heard around town, this attribute doesn't actually work and is broken.

With

nixpkgs_package(
  name = "...-toolchain",
  nix_file = ".circleci/tools.nix",
  attribute_path = "toolchain",

I get

ERROR: /home/grahamc/projects/.../BUILD:15:1: no such package '@...-toolchain//': Not a regular file: /home/grahamc/projects/.../external/.circleci/tools.nix and referenced by '//:...toolchain-impl'

@Fuuzetsu wonders if this is at fault:

if ctx.attr.nix_file and ctx.attr.nix_file_content:
    fail("Specify one of 'nix_file' or 'nix_file_content', but not both.")
  elif ctx.attr.nix_file:
    ctx.symlink(ctx.attr.nix_file, "default.nix")
  elif ctx.attr.nix_file_content:
expr_args = ["-E", ctx.attr.nix_file_content]

Not too sure why we're doing this symlink thing, maybe that's a problem

Deprecate the `path` attribute to `nixpkgs_package`

Path takes a plain string attribute, and then splices it into the NIX_PATH environment variable in the form of:

NIX_PATH=nixpkgs=$path

I argue it breaks the abstraction of bazel handling all your dependencies, since it allows to just reference arbitrary paths. Plus, attr.string isn’t a very specific type, so can be easily used in a wrong way (which leads to strange nix warnings and builds failing).
We should only allow labels in the arguments that build NIX_PATH, which is what #29 achieves.

cc @regnat

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.