From 12f598a2372c6bb6c54c451224c9e05d4eda3212 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Fri, 27 Jan 2023 08:52:42 +0100 Subject: [PATCH 1/5] zig_package & zig_binary end-to-end test --- e2e/workspace/zig-package-binary/BUILD.bazel | 24 +++++++++++++++++++ .../zig-package-binary/data/BUILD.bazel | 11 +++++++++ .../zig-package-binary/data/data.zig | 4 ++++ .../zig-package-binary/data/data/hello.zig | 1 + .../zig-package-binary/data/data/world.zig | 1 + .../zig-package-binary/io/BUILD.bazel | 7 ++++++ e2e/workspace/zig-package-binary/io/io.zig | 5 ++++ e2e/workspace/zig-package-binary/main.zig | 7 ++++++ .../zig-package-binary/output.expected | 1 + 9 files changed, 61 insertions(+) create mode 100644 e2e/workspace/zig-package-binary/BUILD.bazel create mode 100644 e2e/workspace/zig-package-binary/data/BUILD.bazel create mode 100644 e2e/workspace/zig-package-binary/data/data.zig create mode 100644 e2e/workspace/zig-package-binary/data/data/hello.zig create mode 100644 e2e/workspace/zig-package-binary/data/data/world.zig create mode 100644 e2e/workspace/zig-package-binary/io/BUILD.bazel create mode 100644 e2e/workspace/zig-package-binary/io/io.zig create mode 100644 e2e/workspace/zig-package-binary/main.zig create mode 100644 e2e/workspace/zig-package-binary/output.expected diff --git a/e2e/workspace/zig-package-binary/BUILD.bazel b/e2e/workspace/zig-package-binary/BUILD.bazel new file mode 100644 index 00000000..e7faf4aa --- /dev/null +++ b/e2e/workspace/zig-package-binary/BUILD.bazel @@ -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", +) diff --git a/e2e/workspace/zig-package-binary/data/BUILD.bazel b/e2e/workspace/zig-package-binary/data/BUILD.bazel new file mode 100644 index 00000000..38c2418b --- /dev/null +++ b/e2e/workspace/zig-package-binary/data/BUILD.bazel @@ -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__"], +) diff --git a/e2e/workspace/zig-package-binary/data/data.zig b/e2e/workspace/zig-package-binary/data/data.zig new file mode 100644 index 00000000..65d7612d --- /dev/null +++ b/e2e/workspace/zig-package-binary/data/data.zig @@ -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"; diff --git a/e2e/workspace/zig-package-binary/data/data/hello.zig b/e2e/workspace/zig-package-binary/data/data/hello.zig new file mode 100644 index 00000000..dac2d625 --- /dev/null +++ b/e2e/workspace/zig-package-binary/data/data/hello.zig @@ -0,0 +1 @@ +pub const data = "Hello"; diff --git a/e2e/workspace/zig-package-binary/data/data/world.zig b/e2e/workspace/zig-package-binary/data/data/world.zig new file mode 100644 index 00000000..7850d787 --- /dev/null +++ b/e2e/workspace/zig-package-binary/data/data/world.zig @@ -0,0 +1 @@ +pub const data = "World!"; diff --git a/e2e/workspace/zig-package-binary/io/BUILD.bazel b/e2e/workspace/zig-package-binary/io/BUILD.bazel new file mode 100644 index 00000000..4461a240 --- /dev/null +++ b/e2e/workspace/zig-package-binary/io/BUILD.bazel @@ -0,0 +1,7 @@ +load("@rules_zig//zig:defs.bzl", "zig_package") + +zig_package( + name = "io", + main = "io.zig", + visibility = ["//zig-package-binary:__pkg__"], +) diff --git a/e2e/workspace/zig-package-binary/io/io.zig b/e2e/workspace/zig-package-binary/io/io.zig new file mode 100644 index 00000000..83010cbc --- /dev/null +++ b/e2e/workspace/zig-package-binary/io/io.zig @@ -0,0 +1,5 @@ +const std = @import("std"); + +pub fn print(msg: []const u8) void { + std.io.getStdOut().writeAll(msg) catch unreachable; +} diff --git a/e2e/workspace/zig-package-binary/main.zig b/e2e/workspace/zig-package-binary/main.zig new file mode 100644 index 00000000..8de05422 --- /dev/null +++ b/e2e/workspace/zig-package-binary/main.zig @@ -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); +} diff --git a/e2e/workspace/zig-package-binary/output.expected b/e2e/workspace/zig-package-binary/output.expected new file mode 100644 index 00000000..980a0d5f --- /dev/null +++ b/e2e/workspace/zig-package-binary/output.expected @@ -0,0 +1 @@ +Hello World! From bb357911019c863035bff0696ff22fc876c117e5 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sun, 29 Jan 2023 13:59:11 +0100 Subject: [PATCH 2/5] Define the zig_package rule --- docs/rules.md | 20 ++++++++++++ zig/BUILD.bazel | 5 ++- zig/defs.bzl | 2 ++ zig/private/BUILD.bazel | 7 ++++ zig/private/providers/BUILD.bazel | 7 ++++ zig/private/providers/zig_package_info.bzl | 15 +++++++++ zig/private/zig_package.bzl | 38 ++++++++++++++++++++++ 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 zig/private/providers/BUILD.bazel create mode 100644 zig/private/providers/zig_package_info.bzl create mode 100644 zig/private/zig_package.bzl diff --git a/docs/rules.md b/docs/rules.md index 0d50a20a..b2912160 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -22,3 +22,23 @@ zig_binary(name, main< | srcs | Other source files required to build the target. | List of labels | optional | [] | + + +## zig_package + +
+zig_package(name, main, srcs)
+
+ + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| main | The main source file. | Label | required | | +| srcs | Other source files required when building the package. | List of labels | optional | [] | + + diff --git a/zig/BUILD.bazel b/zig/BUILD.bazel index 7432787b..af6f2d61 100644 --- a/zig/BUILD.bazel +++ b/zig/BUILD.bazel @@ -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( diff --git a/zig/defs.bzl b/zig/defs.bzl index 9a9a3fdb..a10850b7 100644 --- a/zig/defs.bzl +++ b/zig/defs.bzl @@ -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 diff --git a/zig/private/BUILD.bazel b/zig/private/BUILD.bazel index 3d0b18e5..9d957667 100644 --- a/zig/private/BUILD.bazel +++ b/zig/private/BUILD.bazel @@ -18,3 +18,10 @@ bzl_library( visibility = ["//zig:__subpackages__"], deps = ["@bazel_skylib//lib:paths"], ) + +bzl_library( + name = "zig_package", + srcs = ["zig_package.bzl"], + visibility = ["//zig:__subpackages__"], + deps = ["//zig/private/providers:zig_package_info"], +) diff --git a/zig/private/providers/BUILD.bazel b/zig/private/providers/BUILD.bazel new file mode 100644 index 00000000..5d159ac3 --- /dev/null +++ b/zig/private/providers/BUILD.bazel @@ -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__"], +) diff --git a/zig/private/providers/zig_package_info.bzl b/zig/private/providers/zig_package_info.bzl new file mode 100644 index 00000000..5f6ed5cd --- /dev/null +++ b/zig/private/providers/zig_package_info.bzl @@ -0,0 +1,15 @@ +"""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, +) diff --git a/zig/private/zig_package.bzl b/zig/private/zig_package.bzl new file mode 100644 index 00000000..2053d98b --- /dev/null +++ b/zig/private/zig_package.bzl @@ -0,0 +1,38 @@ +"""Implementation of the zig_package rule.""" + +load("//zig/private/providers:zig_package_info.bzl", "ZigPackageInfo") + +ZIG_SOURCE_EXTENSIONS = [".zig"] + +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"], +) From 9a91e8cf82a9967a1b86eb7374d4078c2c333c75 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sun, 29 Jan 2023 14:01:32 +0100 Subject: [PATCH 3/5] Factor out ZIG_SOURCE_EXTENSIONS --- zig/private/BUILD.bazel | 16 ++++++++++++++-- zig/private/filetypes.bzl | 3 +++ zig/private/zig_binary.bzl | 3 +-- zig/private/zig_package.bzl | 3 +-- 4 files changed, 19 insertions(+), 6 deletions(-) create mode 100644 zig/private/filetypes.bzl diff --git a/zig/private/BUILD.bazel b/zig/private/BUILD.bazel index 9d957667..17a658d0 100644 --- a/zig/private/BUILD.bazel +++ b/zig/private/BUILD.bazel @@ -16,12 +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 = ["//zig/private/providers:zig_package_info"], + deps = [ + ":filetypes", + "//zig/private/providers:zig_package_info", + ], +) + +bzl_library( + name = "filetypes", + srcs = ["filetypes.bzl"], + visibility = ["//zig:__subpackages__"], ) diff --git a/zig/private/filetypes.bzl b/zig/private/filetypes.bzl new file mode 100644 index 00000000..4f8b54ab --- /dev/null +++ b/zig/private/filetypes.bzl @@ -0,0 +1,3 @@ +"""Define filetypes accepted by rules.""" + +ZIG_SOURCE_EXTENSIONS = [".zig"] diff --git a/zig/private/zig_binary.bzl b/zig/private/zig_binary.bzl index 7b8901c9..6fa3192d 100644 --- a/zig/private/zig_binary.bzl +++ b/zig/private/zig_binary.bzl @@ -1,8 +1,7 @@ """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") DOC = """\ """ diff --git a/zig/private/zig_package.bzl b/zig/private/zig_package.bzl index 2053d98b..be17bd05 100644 --- a/zig/private/zig_package.bzl +++ b/zig/private/zig_package.bzl @@ -1,8 +1,7 @@ """Implementation of the zig_package rule.""" load("//zig/private/providers:zig_package_info.bzl", "ZigPackageInfo") - -ZIG_SOURCE_EXTENSIONS = [".zig"] +load("//zig/private:filetypes.bzl", "ZIG_SOURCE_EXTENSIONS") DOC = """\ """ From 9565d1e555e8d97854c9370fa6cf48c1ca7c5bf7 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sun, 29 Jan 2023 14:22:55 +0100 Subject: [PATCH 4/5] Support zig_package deps on zig_binary --- docs/rules.md | 3 ++- zig/private/providers/zig_package_info.bzl | 16 ++++++++++++++++ zig/private/zig_binary.bzl | 22 +++++++++++++++++++++- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/docs/rules.md b/docs/rules.md index b2912160..9718f51a 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -7,7 +7,7 @@ Public API re-exports ## zig_binary
-zig_binary(name, main, srcs)
+zig_binary(name, deps, main, srcs)
 
@@ -18,6 +18,7 @@ zig_binary(name, main< | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | +| deps | Packages or libraries required to build the target. | List of labels | optional | [] | | main | The main source file. | Label | required | | | srcs | Other source files required to build the target. | List of labels | optional | [] | diff --git a/zig/private/providers/zig_package_info.bzl b/zig/private/providers/zig_package_info.bzl index 5f6ed5cd..72cf0738 100644 --- a/zig/private/providers/zig_package_info.bzl +++ b/zig/private/providers/zig_package_info.bzl @@ -13,3 +13,19 @@ 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) diff --git a/zig/private/zig_binary.bzl b/zig/private/zig_binary.bzl index 6fa3192d..d30abd89 100644 --- a/zig/private/zig_binary.bzl +++ b/zig/private/zig_binary.bzl @@ -2,6 +2,12 @@ load("@bazel_skylib//lib:paths.bzl", "paths") load("//zig/private:filetypes.bzl", "ZIG_SOURCE_EXTENSIONS") +load( + "//zig/private/providers:zig_package_info.bzl", + "ZigPackageInfo", + "add_package_flags", + "get_package_files", +) DOC = """\ """ @@ -17,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): @@ -28,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], From 85d2858af7c5fa39650a446bd6ee9c212f1e4174 Mon Sep 17 00:00:00 2001 From: Andreas Herrmann Date: Sun, 29 Jan 2023 14:49:37 +0100 Subject: [PATCH 5/5] Add unit tests ZigPackageInfo --- zig/tests/BUILD.bazel | 3 + .../multiple-sources-package/BUILD.bazel | 11 +++ zig/tests/multiple-sources-package/data.zig | 4 ++ .../multiple-sources-package/data/hello.zig | 1 + .../multiple-sources-package/data/world.zig | 1 + zig/tests/package_info_test.bzl | 69 +++++++++++++++++++ 6 files changed, 89 insertions(+) create mode 100644 zig/tests/multiple-sources-package/BUILD.bazel create mode 100644 zig/tests/multiple-sources-package/data.zig create mode 100644 zig/tests/multiple-sources-package/data/hello.zig create mode 100644 zig/tests/multiple-sources-package/data/world.zig create mode 100644 zig/tests/package_info_test.bzl diff --git a/zig/tests/BUILD.bazel b/zig/tests/BUILD.bazel index 40b2b2a3..a6204fff 100644 --- a/zig/tests/BUILD.bazel +++ b/zig/tests/BUILD.bazel @@ -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") diff --git a/zig/tests/multiple-sources-package/BUILD.bazel b/zig/tests/multiple-sources-package/BUILD.bazel new file mode 100644 index 00000000..73b70b42 --- /dev/null +++ b/zig/tests/multiple-sources-package/BUILD.bazel @@ -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__"], +) diff --git a/zig/tests/multiple-sources-package/data.zig b/zig/tests/multiple-sources-package/data.zig new file mode 100644 index 00000000..65d7612d --- /dev/null +++ b/zig/tests/multiple-sources-package/data.zig @@ -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"; diff --git a/zig/tests/multiple-sources-package/data/hello.zig b/zig/tests/multiple-sources-package/data/hello.zig new file mode 100644 index 00000000..dac2d625 --- /dev/null +++ b/zig/tests/multiple-sources-package/data/hello.zig @@ -0,0 +1 @@ +pub const data = "Hello"; diff --git a/zig/tests/multiple-sources-package/data/world.zig b/zig/tests/multiple-sources-package/data/world.zig new file mode 100644 index 00000000..7850d787 --- /dev/null +++ b/zig/tests/multiple-sources-package/data/world.zig @@ -0,0 +1 @@ +pub const data = "World!"; diff --git a/zig/tests/package_info_test.bzl b/zig/tests/package_info_test.bzl new file mode 100644 index 00000000..51e9702c --- /dev/null +++ b/zig/tests/package_info_test.bzl @@ -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", + ), + )