Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .bazelrc.common
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,13 @@ test --test_output=errors
test --test_verbose_timeout_warnings
# docs: https://bazel.build/reference/command-line-reference#flag--incompatible_exclusive_test_sandboxed
test --incompatible_exclusive_test_sandboxed

# docs: https://bazel.build/reference/command-line-reference#flag--enable_platform_specific_config
common --enable_platform_specific_config
# Enable persistent Zig cache directory within the sandbox,
# see https://github.com/aherrmann/rules_zig/issues/87,
# and https://github.com/uber/hermetic_cc_toolchain/issues/83.
# docs: https://bazel.build/reference/command-line-reference#flag--sandbox_add_mount_pair
build:linux --sandbox_add_mount_pair=/tmp
build:macos --sandbox_add_mount_pair=/var/tmp
build:windows --sandbox_add_mount_pair=C:\Temp
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ and build configuration features well.
The instructions assume basic familiarity with the Bazel build system.
Take a look at [Bazel's documentation][bazel-intro] if you are unfamiliar.

Consider the [_Additional Setup_](#additional-setup) section as well.

[bazel-intro]: https://bazel.build/about/intro

### Using Bzlmod with Bazel >=6
Expand Down Expand Up @@ -135,6 +137,34 @@ information.

-->

### Additional Setup

#### Zig Cache

The Zig compiler caches intermediate outputs on disk. This cache is shared and
persisted between Bazel builds and build actions. You can configure the cache
directory using the following set of environment variables, you can configure
them through Bazel by using the `--repo_env` flag.

- `RULES_ZIG_CACHE_PREFIX_LINUX`: Cache directory on Linux, default `/tmp/zig-cache`.
- `RULES_ZIG_CACHE_PREFIX_MACOS`: Cache directory on MacOS, default `/var/tmp/zig-cache`.
- `RULES_ZIG_CACHE_PREFIX_WINDOWS`: Cache directory on Windows, default `C:\Temp\zig-cache`.
- `RULES_ZIG_CACHE_PREFIX`: Cache directory fall-back for all platforms, default `/tmp/zig-cache`.

> [!Note]
> On Bazel 7 and above you need to explicitly allow persistence in the sandbox.
> You can use the following `.bazelrc` snippet, adjust the paths depending on
> your cache configuration.
>
> ```
> common --enable_platform_specific_config
> # You can configure `/tmp/zig-cache`, or similar, specifically,
> # if you can ensure that the directory exists before the build.
> build:linux --sandbox_add_mount_pair=/tmp
> build:macos --sandbox_add_mount_pair=/var/tmp
> build:windows --sandbox_add_mount_pair=C:\Temp
> ```

## Usage Examples

<!-- TODO[AH] Create an instructive example.
Expand Down
8 changes: 8 additions & 0 deletions docs/repositories.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion docs/toolchains.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions zig/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ bzl_library(
":bazel_tools",
"//zig/private:toolchains_repo",
"//zig/private:versions",
"//zig/private/common:zig_cache",
],
)

Expand Down
4 changes: 1 addition & 3 deletions zig/private/common/zig_build.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -251,9 +251,7 @@ def zig_build_impl(ctx, *, kind):
)

zig_cache_output(
actions = ctx.actions,
name = ctx.label.name,
outputs = outputs,
zigtoolchaininfo = zigtoolchaininfo,
args = args,
)

Expand Down
51 changes: 35 additions & 16 deletions zig/private/common/zig_cache.bzl
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
"""Defines utilities to handle the Zig compiler cache."""

load("@bazel_skylib//lib:paths.bzl", "paths")
VAR_CACHE_PREFIX = "RULES_ZIG_CACHE_PREFIX"
VAR_CACHE_PREFIX_LINUX = "RULES_ZIG_CACHE_PREFIX_LINUX"
VAR_CACHE_PREFIX_MACOS = "RULES_ZIG_CACHE_PREFIX_MACOS"
VAR_CACHE_PREFIX_WINDOWS = "RULES_ZIG_CACHE_PREFIX_WINDOWS"

def zig_cache_output(*, actions, name, outputs, args):
"""Handle the Zig compiler cache.
DEFAULT_CACHE_PREFIX = "/tmp/zig-cache"
DEFAULT_CACHE_PREFIX_LINUX = "/tmp/zig-cache"
DEFAULT_CACHE_PREFIX_MACOS = "/var/tmp/zig-cache"
DEFAULT_CACHE_PREFIX_WINDOWS = "C:\\Temp\\zig-cache"

Declares directory outputs for the local and global Zig compiler cache.
Appends both to the given outputs list, and arguments object.
def env_zig_cache_prefix(environ, platform):
"""Determine the appropriate Zig cache prefix for the given platform.

Args:
actions: `ctx.actions`.
name: String, A unique name to distinguish this cache from others.
outputs: List; mutable, Append the declared outputs to this list.
args: Args; mutable, Append the Zig cache flags to this object.
environ: dict, The environment variables.
platform: string, The name of the toolchain execution platform.

Returns:
The Zig cache prefix path.
"""
if platform.find("linux") != -1:
cache_prefix = environ.get(VAR_CACHE_PREFIX_LINUX, environ.get(VAR_CACHE_PREFIX, DEFAULT_CACHE_PREFIX_LINUX))
elif platform.find("macos") != -1:
cache_prefix = environ.get(VAR_CACHE_PREFIX_MACOS, environ.get(VAR_CACHE_PREFIX, DEFAULT_CACHE_PREFIX_MACOS))
elif platform.find("windows") != -1:
cache_prefix = environ.get(VAR_CACHE_PREFIX_WINDOWS, environ.get(VAR_CACHE_PREFIX, DEFAULT_CACHE_PREFIX_WINDOWS))
else:
cache_prefix = environ.get(VAR_CACHE_PREFIX, DEFAULT_CACHE_PREFIX)

return cache_prefix

# TODO[AH] Persist or share at least the global cache somehow.
local_cache = actions.declare_directory(paths.join(".zig-cache", "local", name))
global_cache = actions.declare_directory(paths.join(".zig-cache", "global", name))
def zig_cache_output(*, zigtoolchaininfo, args):
"""Handle the Zig compiler cache.

outputs.append(local_cache)
outputs.append(global_cache)
Configures the local and global cache based on the given cache prefix path.
The cache is not a Bazel managed input or output of the build action.

args.add_all(["--cache-dir", local_cache.path])
args.add_all(["--global-cache-dir", global_cache.path])
Args:
zigtoolchaininfo: ZigToolchainInfo.
args: Args; mutable, Append the Zig cache flags to this object.
"""
args.add_all(["--cache-dir", zigtoolchaininfo.zig_cache])
args.add_all(["--global-cache-dir", zigtoolchaininfo.zig_cache])
4 changes: 1 addition & 3 deletions zig/private/common/zig_docs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,7 @@ def zig_docs_impl(ctx, *, kind):
)

zig_cache_output(
actions = ctx.actions,
name = ctx.label.name + "-docs",
outputs = outputs,
zigtoolchaininfo = zigtoolchaininfo,
args = args,
)

Expand Down
1 change: 1 addition & 0 deletions zig/private/providers/zig_toolchain_info.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Files required in runfiles to make the Zig executable available.
May be empty if the zig_exe_path points to a locally installed Zig executable.
""",
"zig_version": "String, The Zig toolchain's version.",
"zig_cache": "String, The Zig cache directory prefix used for the global and local cache.",
}

ZigToolchainInfo = provider(
Expand Down
6 changes: 6 additions & 0 deletions zig/private/zig_toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ ATTRS = {
doc = "The Zig toolchain's version.",
mandatory = True,
),
"zig_cache": attr.string(
doc = "The Zig cache directory prefix. Used for both the global and local cache.",
mandatory = True,
),
}

# Avoid using non-normalized paths (workspace/../other_workspace/path)
Expand Down Expand Up @@ -101,6 +105,7 @@ def _zig_toolchain_impl(ctx):
zig_exe_path = ctx.attr.zig_exe_path
zig_lib_path = ctx.attr.zig_lib_path
zig_version = ctx.attr.zig_version
zig_cache = ctx.attr.zig_cache

if ctx.attr.zig_exe:
zig_files = ctx.attr.zig_exe.files.to_list() + ctx.files.zig_lib
Expand Down Expand Up @@ -135,6 +140,7 @@ def _zig_toolchain_impl(ctx):
zig_lib_path = zig_lib_path,
zig_files = zig_files,
zig_version = zig_version,
zig_cache = zig_cache,
)

# Export all the providers inside our ToolchainInfo
Expand Down
19 changes: 19 additions & 0 deletions zig/repositories.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", __http_archive = "http_arch
load("@bazel_tools//tools/build_defs/repo:utils.bzl", "maybe")
load("//zig/private:toolchains_repo.bzl", "PLATFORMS", "toolchains_repo")
load("//zig/private:versions.bzl", "TOOL_VERSIONS")
load(
"//zig/private/common:zig_cache.bzl",
"VAR_CACHE_PREFIX",
"VAR_CACHE_PREFIX_LINUX",
"VAR_CACHE_PREFIX_MACOS",
"VAR_CACHE_PREFIX_WINDOWS",
"env_zig_cache_prefix",
)

def _http_archive(name, **kwargs):
maybe(__http_archive, name = name, **kwargs)
Expand Down Expand Up @@ -46,6 +54,12 @@ _ATTRS = {
"zig_version": attr.string(mandatory = True, values = TOOL_VERSIONS.keys()),
"platform": attr.string(mandatory = True, values = PLATFORMS.keys()),
}
_ENV = [
VAR_CACHE_PREFIX,
VAR_CACHE_PREFIX_LINUX,
VAR_CACHE_PREFIX_MACOS,
VAR_CACHE_PREFIX_WINDOWS,
]

def _zig_repo_impl(repository_ctx):
url = TOOL_VERSIONS[repository_ctx.attr.zig_version][repository_ctx.attr.platform].url
Expand All @@ -63,6 +77,8 @@ def _zig_repo_impl(repository_ctx):
stripPrefix = prefix,
)

cache_prefix = env_zig_cache_prefix(repository_ctx.os.environ, repository_ctx.attr.platform)

build_content = """#Generated by zig/repositories.bzl
load("@rules_zig//zig:toolchain.bzl", "zig_toolchain")
zig_toolchain(
Expand All @@ -74,9 +90,11 @@ zig_toolchain(
zig_lib = glob(["lib/**"]),
zig_lib_path = "lib",
zig_version = "{zig_version}",
zig_cache = {zig_cache},
)
""".format(
zig_version = repository_ctx.attr.zig_version,
zig_cache = repr(cache_prefix),
)

# Base BUILD file for this repository
Expand All @@ -86,6 +104,7 @@ zig_repositories = repository_rule(
_zig_repo_impl,
doc = _DOC,
attrs = _ATTRS,
environ = _ENV,
)

# Wrapper macro around everything above, this is the primary API
Expand Down
3 changes: 3 additions & 0 deletions zig/tests/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load(":cache_test.bzl", "cache_test_suite")
load(":config_test.bzl", "config_test_suite")
load(":mode_test.bzl", "mode_test_suite")
load(":module_info_test.bzl", "module_info_test_suite")
Expand All @@ -8,6 +9,8 @@ load(":target_triple_test.bzl", "target_triple_test_suite")
load(":threaded_test.bzl", "threaded_test_suite")
load(":versions_test.bzl", "versions_test_suite")

cache_test_suite(name = "cache_test")

config_test_suite(name = "config_test")

mode_test_suite(name = "mode_test")
Expand Down
Loading