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
23 changes: 22 additions & 1 deletion docs/rules.md

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

24 changes: 24 additions & 0 deletions e2e/workspace/zig-package-binary/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
load("@rules_zig//zig:defs.bzl", "zig_binary")

zig_binary(
name = "binary",
main = "main.zig",
deps = [
"//zig-package-binary/data",
"//zig-package-binary/io",
],
)

genrule(
name = "output",
outs = ["output.actual"],
cmd = "$(execpath :binary) > $(OUTS)",
tools = [":binary"],
)

diff_test(
name = "output_test",
file1 = ":output.expected",
file2 = ":output.actual",
)
11 changes: 11 additions & 0 deletions e2e/workspace/zig-package-binary/data/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
load("@rules_zig//zig:defs.bzl", "zig_package")

zig_package(
name = "data",
srcs = [
"data/hello.zig",
"data/world.zig",
],
main = "data.zig",
visibility = ["//zig-package-binary:__pkg__"],
)
4 changes: 4 additions & 0 deletions e2e/workspace/zig-package-binary/data/data.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const hello = @import("data/hello.zig");
const world = @import("data/world.zig");

pub const hello_world = hello.data ++ " " ++ world.data ++ "\n";
1 change: 1 addition & 0 deletions e2e/workspace/zig-package-binary/data/data/hello.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const data = "Hello";
1 change: 1 addition & 0 deletions e2e/workspace/zig-package-binary/data/data/world.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const data = "World!";
7 changes: 7 additions & 0 deletions e2e/workspace/zig-package-binary/io/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
load("@rules_zig//zig:defs.bzl", "zig_package")

zig_package(
name = "io",
main = "io.zig",
visibility = ["//zig-package-binary:__pkg__"],
)
5 changes: 5 additions & 0 deletions e2e/workspace/zig-package-binary/io/io.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const std = @import("std");

pub fn print(msg: []const u8) void {
std.io.getStdOut().writeAll(msg) catch unreachable;
}
7 changes: 7 additions & 0 deletions e2e/workspace/zig-package-binary/main.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const std = @import("std");
const data = @import("data");
const io = @import("io");

pub fn main() void {
io.print(data.hello_world);
}
1 change: 1 addition & 0 deletions e2e/workspace/zig-package-binary/output.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Hello World!
5 changes: 4 additions & 1 deletion zig/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,10 @@ bzl_library(
name = "defs",
srcs = ["defs.bzl"],
visibility = ["//visibility:public"],
deps = ["//zig/private:zig_binary"],
deps = [
"//zig/private:zig_binary",
"//zig/private:zig_package",
],
)

bzl_library(
Expand Down
2 changes: 2 additions & 0 deletions zig/defs.bzl
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
"Public API re-exports"

load("//zig/private:zig_binary.bzl", _zig_binary = "zig_binary")
load("//zig/private:zig_package.bzl", _zig_package = "zig_package")

zig_binary = _zig_binary
zig_package = _zig_package
21 changes: 20 additions & 1 deletion zig/private/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,24 @@ bzl_library(
name = "zig_binary",
srcs = ["zig_binary.bzl"],
visibility = ["//zig:__subpackages__"],
deps = ["@bazel_skylib//lib:paths"],
deps = [
":filetypes",
"@bazel_skylib//lib:paths",
],
)

bzl_library(
name = "zig_package",
srcs = ["zig_package.bzl"],
visibility = ["//zig:__subpackages__"],
deps = [
":filetypes",
"//zig/private/providers:zig_package_info",
],
)

bzl_library(
name = "filetypes",
srcs = ["filetypes.bzl"],
visibility = ["//zig:__subpackages__"],
)
3 changes: 3 additions & 0 deletions zig/private/filetypes.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Define filetypes accepted by rules."""

ZIG_SOURCE_EXTENSIONS = [".zig"]
7 changes: 7 additions & 0 deletions zig/private/providers/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")

bzl_library(
name = "zig_package_info",
srcs = ["zig_package_info.bzl"],
visibility = ["//zig:__subpackages__"],
)
31 changes: 31 additions & 0 deletions zig/private/providers/zig_package_info.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Defines providers for the zig_package rule."""

DOC = """\
"""

FIELDS = {
"name": "The import name of the package.",
"main": "The main source file of the package.",
"srcs": "Other source files required when building the package.",
}

ZigPackageInfo = provider(
fields = FIELDS,
doc = DOC,
)

def add_package_flags(args, package):
"""Generate the Zig compiler flags to depend on the given package.

Generates `--pkg-begin` and `--pkg-end` flags required to build a target
that depends on this package.

Args:
args: The Args object to extend with the required flags.
package: The package to generate flags for.
"""
args.add_all(["--pkg-begin", package.name, package.main, "--pkg-end"])

def get_package_files(package):
"""Generate a `depset` of the files required to depend on the package."""
return depset([package.main] + package.srcs)
25 changes: 22 additions & 3 deletions zig/private/zig_binary.bzl
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"""Implementation of the zig_binary rule."""

load("@bazel_skylib//lib:paths.bzl", "paths")

ZIG_SOURCE_EXTENSIONS = [".zig"]
load("//zig/private:filetypes.bzl", "ZIG_SOURCE_EXTENSIONS")
load(
"//zig/private/providers:zig_package_info.bzl",
"ZigPackageInfo",
"add_package_flags",
"get_package_files",
)

DOC = """\
"""
Expand All @@ -18,6 +23,11 @@ ATTRS = {
doc = "Other source files required to build the target.",
mandatory = False,
),
"deps": attr.label_list(
doc = "Packages or libraries required to build the target.",
mandatory = False,
providers = [ZigPackageInfo],
),
}

def _zig_binary_impl(ctx):
Expand All @@ -29,19 +39,28 @@ def _zig_binary_impl(ctx):
local_cache = ctx.actions.declare_directory(paths.join(".zig-cache", "local", ctx.label.name))
global_cache = ctx.actions.declare_directory(paths.join(".zig-cache", "global", ctx.label.name))

direct_inputs = [ctx.file.main] + ctx.files.srcs
transitive_inputs = []

args = ctx.actions.args()
args.use_param_file("@%s")

args.add(output, format = "-femit-bin=%s")
args.add(ctx.file.main)

for dep in ctx.attr.deps:
if ZigPackageInfo in dep:
package = dep[ZigPackageInfo]
transitive_inputs.append(get_package_files(package))
add_package_flags(args, package)

# TODO[AH] Persist or share at least the global cache somehow.
args.add_all(["--cache-dir", local_cache.path])
args.add_all(["--global-cache-dir", global_cache.path])

ctx.actions.run(
outputs = [output, local_cache, global_cache],
inputs = [ctx.file.main] + ctx.files.srcs,
inputs = depset(direct = direct_inputs, transitive = transitive_inputs),
executable = ziginfo.target_tool_path,
tools = ziginfo.tool_files,
arguments = ["build-exe", args],
Expand Down
37 changes: 37 additions & 0 deletions zig/private/zig_package.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
"""Implementation of the zig_package rule."""

load("//zig/private/providers:zig_package_info.bzl", "ZigPackageInfo")
load("//zig/private:filetypes.bzl", "ZIG_SOURCE_EXTENSIONS")

DOC = """\
"""

ATTRS = {
"main": attr.label(
allow_single_file = ZIG_SOURCE_EXTENSIONS,
doc = "The main source file.",
mandatory = True,
),
"srcs": attr.label_list(
allow_files = ZIG_SOURCE_EXTENSIONS,
doc = "Other source files required when building the package.",
mandatory = False,
),
}

def _zig_package_impl(ctx):
default = DefaultInfo(
)
package = ZigPackageInfo(
name = ctx.label.name,
main = ctx.file.main,
srcs = ctx.files.srcs,
)
return [default, package]

zig_package = rule(
_zig_package_impl,
attrs = ATTRS,
doc = DOC,
toolchains = ["//zig:toolchain_type"],
)
3 changes: 3 additions & 0 deletions zig/tests/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
load(":rules_test.bzl", "rules_test_suite")
load(":package_info_test.bzl", "package_info_test_suite")
load(":versions_test.bzl", "versions_test_suite")

rules_test_suite(name = "rules_test")

package_info_test_suite(name = "package_info_test")

versions_test_suite(name = "versions_test")
11 changes: 11 additions & 0 deletions zig/tests/multiple-sources-package/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
load("@rules_zig//zig:defs.bzl", "zig_package")

zig_package(
name = "data",
srcs = [
"data/hello.zig",
"data/world.zig",
],
main = "data.zig",
visibility = ["//zig/tests:__pkg__"],
)
4 changes: 4 additions & 0 deletions zig/tests/multiple-sources-package/data.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
const hello = @import("data/hello.zig");
const world = @import("data/world.zig");

pub const hello_world = hello.data ++ " " ++ world.data ++ "\n";
1 change: 1 addition & 0 deletions zig/tests/multiple-sources-package/data/hello.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const data = "Hello";
1 change: 1 addition & 0 deletions zig/tests/multiple-sources-package/data/world.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub const data = "World!";
69 changes: 69 additions & 0 deletions zig/tests/package_info_test.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"""Unit tests for ZigPackageInfo functions.
"""

load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
load("@bazel_skylib//lib:sets.bzl", "sets")
load(
"//zig/private/providers:zig_package_info.bzl",
"ZigPackageInfo",
"add_package_flags",
"get_package_files",
)

def _mock_args():
self_args = []

def add_all(args):
for arg in args:
if type(arg) == "File":
self_args.append(arg.path)
else:
self_args.append(arg)

def get_args():
return self_args

return struct(
add_all = add_all,
get_args = get_args,
)

def _single_package_test_impl(ctx):
env = unittest.begin(ctx)

package = ctx.attr.pkg[ZigPackageInfo]

args = _mock_args()
add_package_flags(args, package)
asserts.equals(
env,
["--pkg-begin", package.name, package.main.path, "--pkg-end"],
args.get_args(),
"add_package_flags should generate the expected arguments.",
)

files = get_package_files(package)
asserts.set_equals(
env,
sets.make([package.main] + package.srcs),
sets.make(files.to_list()),
"get_package_files should capture all package files.",
)

return unittest.end(env)

_single_package_test = unittest.make(
_single_package_test_impl,
attrs = {
"pkg": attr.label(providers = [ZigPackageInfo]),
},
)

def package_info_test_suite(name):
unittest.suite(
name,
lambda name: _single_package_test(
name = name,
pkg = "//zig/tests/multiple-sources-package:data",
),
)