diff --git a/.bazelrc b/.bazelrc index ee01b8b0..c4012a82 100644 --- a/.bazelrc +++ b/.bazelrc @@ -7,8 +7,8 @@ import %workspace%/.bazelrc.flags # Deleted packages for integration tests. # To update these lines, execute # `bazel run @rules_bazel_integration_test//tools:update_deleted_packages` -build --deleted_packages=e2e/workspace,e2e/workspace/c-sources,e2e/workspace/configure-mode,e2e/workspace/configure-target,e2e/workspace/configure-threaded,e2e/workspace/embed-file,e2e/workspace/linker-script,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace -query --deleted_packages=e2e/workspace,e2e/workspace/c-sources,e2e/workspace/configure-mode,e2e/workspace/configure-target,e2e/workspace/configure-threaded,e2e/workspace/embed-file,e2e/workspace/linker-script,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace +build --deleted_packages=e2e/workspace,e2e/workspace/c-sources,e2e/workspace/configure-mode,e2e/workspace/configure-target,e2e/workspace/configure-threaded,e2e/workspace/data-dependencies,e2e/workspace/embed-file,e2e/workspace/linker-script,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace +query --deleted_packages=e2e/workspace,e2e/workspace/c-sources,e2e/workspace/configure-mode,e2e/workspace/configure-target,e2e/workspace/configure-threaded,e2e/workspace/data-dependencies,e2e/workspace/embed-file,e2e/workspace/linker-script,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace # Load any settings specific to the current user. # .bazelrc.user should appear in .gitignore so that settings are not shared with team members diff --git a/docs/rules.md b/docs/rules.md index 0eb2b6a3..23f494b4 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -7,7 +7,7 @@ Rules to build and run Zig code. ## zig_binary
-zig_binary(name, copts, csrcs, deps, extra_srcs, linker_script, main, srcs)
+zig_binary(name, copts, csrcs, data, deps, extra_srcs, linker_script, main, srcs)
 
Builds a Zig binary. @@ -41,6 +41,7 @@ zig_binary( | name | A unique name for this target. | Name | required | | | copts | C compiler flags required to build the C sources of the target. | List of strings | optional | [] | | csrcs | C source files required to build the target. | List of labels | optional | [] | +| data | Files required by the target during runtime. | List of labels | optional | [] | | deps | Packages or libraries required to build the target. | List of labels | optional | [] | | extra_srcs | Other files required to build the target, e.g. files embedded using @embedFile. | List of labels | optional | [] | | linker_script | Custom linker script for the target. | Label | optional | None | @@ -236,7 +237,7 @@ zig_configure_test( ## zig_library
-zig_library(name, copts, csrcs, deps, extra_srcs, linker_script, main, srcs)
+zig_library(name, copts, csrcs, data, deps, extra_srcs, linker_script, main, srcs)
 
Builds a Zig library. @@ -269,6 +270,7 @@ zig_library( | name | A unique name for this target. | Name | required | | | copts | C compiler flags required to build the C sources of the target. | List of strings | optional | [] | | csrcs | C source files required to build the target. | List of labels | optional | [] | +| data | Files required by the target during runtime. | List of labels | optional | [] | | deps | Packages or libraries required to build the target. | List of labels | optional | [] | | extra_srcs | Other files required to build the target, e.g. files embedded using @embedFile. | List of labels | optional | [] | | linker_script | Custom linker script for the target. | Label | optional | None | @@ -281,7 +283,7 @@ zig_library( ## zig_package
-zig_package(name, deps, extra_srcs, main, srcs)
+zig_package(name, data, deps, extra_srcs, main, srcs)
 
Defines a Zig package. @@ -317,6 +319,7 @@ zig_package( | Name | Description | Type | Mandatory | Default | | :------------- | :------------- | :------------- | :------------- | :------------- | | name | A unique name for this target. | Name | required | | +| data | Files required by the package during runtime. | List of labels | optional | [] | | deps | Other packages required when building the package.

Note, the Zig compiler requires that every package dependency is specified with its own package dependencies on the command-line, recursively. Meaning the entire Zig package dependency tree will be represented on the command-line without deduplication of shared nodes. Keep this in mind when you defined the granularity of your Zig packages. | List of labels | optional | [] | | extra_srcs | Other files required when building the package, e.g. files embedded using @embedFile. | List of labels | optional | [] | | main | The main source file. | Label | required | | @@ -328,7 +331,7 @@ zig_package( ## zig_test
-zig_test(name, copts, csrcs, deps, extra_srcs, linker_script, main, srcs)
+zig_test(name, copts, csrcs, data, deps, extra_srcs, linker_script, main, srcs)
 
Builds a Zig test. @@ -361,6 +364,7 @@ zig_test( | name | A unique name for this target. | Name | required | | | copts | C compiler flags required to build the C sources of the target. | List of strings | optional | [] | | csrcs | C source files required to build the target. | List of labels | optional | [] | +| data | Files required by the target during runtime. | List of labels | optional | [] | | deps | Packages or libraries required to build the target. | List of labels | optional | [] | | extra_srcs | Other files required to build the target, e.g. files embedded using @embedFile. | List of labels | optional | [] | | linker_script | Custom linker script for the target. | Label | optional | None | diff --git a/e2e/workspace/data-dependencies/BUILD.bazel b/e2e/workspace/data-dependencies/BUILD.bazel new file mode 100644 index 00000000..36e519a8 --- /dev/null +++ b/e2e/workspace/data-dependencies/BUILD.bazel @@ -0,0 +1,31 @@ +load("@rules_zig//zig:defs.bzl", "zig_package", "zig_test") + +zig_test( + name = "direct-data", + data = ["data.txt"], + main = "direct-data.zig", +) + +zig_package( + name = "direct-package", + data = ["data.txt"], + main = "direct-package.zig", +) + +zig_test( + name = "direct-package-data", + main = "direct-package-data.zig", + deps = [":direct-package"], +) + +zig_package( + name = "indirect-package", + main = "indirect-package.zig", + deps = [":direct-package"], +) + +zig_test( + name = "indirect-package-data", + main = "indirect-package-data.zig", + deps = [":indirect-package"], +) diff --git a/e2e/workspace/data-dependencies/data.txt b/e2e/workspace/data-dependencies/data.txt new file mode 100644 index 00000000..980a0d5f --- /dev/null +++ b/e2e/workspace/data-dependencies/data.txt @@ -0,0 +1 @@ +Hello World! diff --git a/e2e/workspace/data-dependencies/direct-data.zig b/e2e/workspace/data-dependencies/direct-data.zig new file mode 100644 index 00000000..347dc385 --- /dev/null +++ b/e2e/workspace/data-dependencies/direct-data.zig @@ -0,0 +1,11 @@ +const std = @import("std"); + +test "read data file" { + var file = try std.fs.cwd().openFile("data-dependencies/data.txt", .{}); + defer file.close(); + + const content = try file.readToEndAlloc(std.testing.allocator, 4096); + defer std.testing.allocator.free(content); + + try std.testing.expectEqualStrings("Hello World!\n", content); +} diff --git a/e2e/workspace/data-dependencies/direct-package-data.zig b/e2e/workspace/data-dependencies/direct-package-data.zig new file mode 100644 index 00000000..95f90109 --- /dev/null +++ b/e2e/workspace/data-dependencies/direct-package-data.zig @@ -0,0 +1,9 @@ +const std = @import("std"); +const direct_package = @import("direct-package"); + +test "read data file" { + const content = try direct_package.readData(std.testing.allocator); + defer std.testing.allocator.free(content); + + try std.testing.expectEqualStrings("Hello World!\n", content); +} diff --git a/e2e/workspace/data-dependencies/direct-package.zig b/e2e/workspace/data-dependencies/direct-package.zig new file mode 100644 index 00000000..321551cd --- /dev/null +++ b/e2e/workspace/data-dependencies/direct-package.zig @@ -0,0 +1,10 @@ +const std = @import("std"); + +pub fn readData(allocator: std.mem.Allocator) ![]u8 { + var file = try std.fs.cwd().openFile("data-dependencies/data.txt", .{}); + defer file.close(); + + const content = try file.readToEndAlloc(allocator, 4096); + + return content; +} diff --git a/e2e/workspace/data-dependencies/indirect-package-data.zig b/e2e/workspace/data-dependencies/indirect-package-data.zig new file mode 100644 index 00000000..5d67cdd5 --- /dev/null +++ b/e2e/workspace/data-dependencies/indirect-package-data.zig @@ -0,0 +1,9 @@ +const std = @import("std"); +const indirect_package = @import("indirect-package"); + +test "read data file" { + const content = try indirect_package.readData(std.testing.allocator); + defer std.testing.allocator.free(content); + + try std.testing.expectEqualStrings("Hello World!\n", content); +} diff --git a/e2e/workspace/data-dependencies/indirect-package.zig b/e2e/workspace/data-dependencies/indirect-package.zig new file mode 100644 index 00000000..5f5cdc0e --- /dev/null +++ b/e2e/workspace/data-dependencies/indirect-package.zig @@ -0,0 +1,3 @@ +const direct_package = @import("direct-package"); + +pub const readData = direct_package.readData; diff --git a/zig/private/BUILD.bazel b/zig/private/BUILD.bazel index 5f806bd9..89e68bc9 100644 --- a/zig/private/BUILD.bazel +++ b/zig/private/BUILD.bazel @@ -5,6 +5,7 @@ bzl_library( srcs = ["zig_package.bzl"], visibility = ["//zig:__subpackages__"], deps = [ + "//zig/private/common:data", "//zig/private/common:filetypes", "//zig/private/providers:zig_package_info", ], diff --git a/zig/private/common/BUILD.bazel b/zig/private/common/BUILD.bazel index 9aa144b9..d7941c96 100644 --- a/zig/private/common/BUILD.bazel +++ b/zig/private/common/BUILD.bazel @@ -20,6 +20,7 @@ bzl_library( visibility = ["//zig:__subpackages__"], deps = [ ":csrcs", + ":data", ":filetypes", ":linker_script", ":zig_cache", @@ -36,6 +37,12 @@ bzl_library( visibility = ["//zig:__subpackages__"], ) +bzl_library( + name = "data", + srcs = ["data.bzl"], + visibility = ["//zig:__subpackages__"], +) + bzl_library( name = "filetypes", srcs = ["filetypes.bzl"], @@ -54,6 +61,7 @@ filegroup( srcs = [ ":BUILD.bazel", ":csrcs.bzl", + ":data.bzl", ":filetypes.bzl", ":linker_script.bzl", ":zig_build.bzl", diff --git a/zig/private/common/data.bzl b/zig/private/common/data.bzl new file mode 100644 index 00000000..296035b6 --- /dev/null +++ b/zig/private/common/data.bzl @@ -0,0 +1,39 @@ +"""Handle runtime data dependencies.""" + +def zig_collect_data(*, data, deps, transitive_data, transitive_runfiles): + """Handle data dependencies. + + Collects runtime data from the given dependencies. + Data dependency attributes will contribute both, + their output files and their own runtime data dependencies. + Other dependency attributes will only contribute + their own runtime data dependencies. + + Args: + data: List of Target, Data dependency attributes. + deps: List of Target, Other dependency attributes. + transitive_data: List of depset of File; mutable, Append data file dependencies. + transitive_runfiles: List of runfiles; mutable, Append runfile dependencies. + """ + for data in data: + transitive_data.append(data[DefaultInfo].files) + transitive_runfiles.append(data[DefaultInfo].default_runfiles) + + for dep in deps: + transitive_runfiles.append(dep[DefaultInfo].default_runfiles) + +def zig_create_runfiles(*, ctx_runfiles, direct_data, transitive_data, transitive_runfiles): + """Create a new runfiles object. + + The newly created runfiles will bundle all provided data files and runfiles. + + Args: + ctx_runfiles: Runfiles constructor function. + direct_data: List of File, Data files. + transitive_data: List of depset of File, Data files. + transitive_runfiles: List of depset of File, Runfiles. + """ + return ctx_runfiles( + files = direct_data, + transitive_files = depset(transitive = transitive_data), + ).merge_all(transitive_runfiles) diff --git a/zig/private/common/zig_build.bzl b/zig/private/common/zig_build.bzl index 25ae37cc..252a855d 100644 --- a/zig/private/common/zig_build.bzl +++ b/zig/private/common/zig_build.bzl @@ -6,6 +6,7 @@ load( "ZIG_SOURCE_EXTENSIONS", ) load("//zig/private/common:csrcs.bzl", "zig_csrcs") +load("//zig/private/common:data.bzl", "zig_collect_data", "zig_create_runfiles") load("//zig/private/common:linker_script.bzl", "zig_linker_script") load("//zig/private/common:zig_cache.bzl", "zig_cache_output") load("//zig/private/common:zig_lib_dir.bzl", "zig_lib_dir") @@ -59,6 +60,11 @@ ATTRS = { allow_single_file = True, mandatory = False, ), + "data": attr.label_list( + allow_files = True, + doc = "Files required by the target during runtime.", + mandatory = False, + ), "_settings": attr.label( default = "//zig/settings", doc = "Zig build settings.", @@ -84,15 +90,24 @@ def zig_build_impl(ctx, *, kind): zigtoolchaininfo = ctx.toolchains["//zig:toolchain_type"].zigtoolchaininfo zigtargetinfo = ctx.toolchains["//zig/target:toolchain_type"].zigtargetinfo - default_executable = None - default_files = None - default_runfiles = None + executable = None + files = None + direct_data = [] + transitive_data = [] + transitive_runfiles = [] outputs = [] direct_inputs = [] transitive_inputs = [] + zig_collect_data( + data = ctx.attr.data, + deps = ctx.attr.deps, + transitive_data = transitive_data, + transitive_runfiles = transitive_runfiles, + ) + args = ctx.actions.args() args.use_param_file("@%s") @@ -102,9 +117,9 @@ def zig_build_impl(ctx, *, kind): outputs.append(output) args.add(output, format = "-femit-bin=%s") - default_executable = output - default_files = depset([output]) - default_runfiles = ctx.runfiles(files = [output]) + executable = output + files = depset([output]) + direct_data.append(output) elif kind == "zig_library": # TODO[AH] Set `.lib` extension on Windows. static = ctx.actions.declare_file(ctx.label.name + ".a") @@ -112,7 +127,7 @@ def zig_build_impl(ctx, *, kind): args.add(static, format = "-femit-bin=%s") # TODO[AH] Support dynamic library output. - default_files = depset([static]) + files = depset([static]) else: fail("Unknown rule kind '{}'.".format(kind)) @@ -195,9 +210,14 @@ def zig_build_impl(ctx, *, kind): ) default = DefaultInfo( - executable = default_executable, - files = default_files, - runfiles = default_runfiles, + executable = executable, + files = files, + runfiles = zig_create_runfiles( + ctx_runfiles = ctx.runfiles, + direct_data = [], + transitive_data = transitive_data, + transitive_runfiles = transitive_runfiles, + ), ) return [default] diff --git a/zig/private/zig_package.bzl b/zig/private/zig_package.bzl index a567f222..6126764f 100644 --- a/zig/private/zig_package.bzl +++ b/zig/private/zig_package.bzl @@ -1,5 +1,6 @@ """Implementation of the zig_package rule.""" +load("//zig/private/common:data.bzl", "zig_collect_data", "zig_create_runfiles") load("//zig/private/common:filetypes.bzl", "ZIG_SOURCE_EXTENSIONS") load("//zig/private/providers:zig_package_info.bzl", "ZigPackageInfo") @@ -60,10 +61,31 @@ granularity of your Zig packages. mandatory = False, providers = [ZigPackageInfo], ), + "data": attr.label_list( + allow_files = True, + doc = "Files required by the package during runtime.", + mandatory = False, + ), } def _zig_package_impl(ctx): + transitive_data = [] + transitive_runfiles = [] + + zig_collect_data( + data = ctx.attr.data, + deps = ctx.attr.deps, + transitive_data = transitive_data, + transitive_runfiles = transitive_runfiles, + ) + default = DefaultInfo( + runfiles = zig_create_runfiles( + ctx_runfiles = ctx.runfiles, + direct_data = [], + transitive_data = transitive_data, + transitive_runfiles = transitive_runfiles, + ), ) srcs = [ctx.file.main] + ctx.files.srcs + ctx.files.extra_srcs