Inital commit

This commit is contained in:
eric
2026-03-12 18:58:43 +01:00
commit 8555b02752
36 changed files with 3312 additions and 0 deletions

1
BUILD.bazel Normal file
View File

@@ -0,0 +1 @@
exports_files(["README.md"])

36
MODULE.bazel Normal file
View File

@@ -0,0 +1,36 @@
module(
name = "rules_wails",
version = "0.1.0",
)
bazel_dep(
name = "rules_go",
repo_name = "io_bazel_rules_go",
version = "0.60.0",
)
bazel_dep(name = "rules_bun", version = "0.2.3")
bazel_dep(name = "rules_shell", version = "0.6.1")
archive_override(
module_name = "rules_bun",
strip_prefix = "rules_bun",
urls = ["https://git.dgren.dev/eric/rules_bun/archive/v0.2.3.tar.gz"],
)
bun_ext = use_extension("@rules_bun//bun:extensions.bzl", "bun")
use_repo(
bun_ext,
"bun_darwin_aarch64",
"bun_darwin_x64",
"bun_linux_aarch64",
"bun_linux_x64",
"bun_windows_x64",
)
register_toolchains(
"@rules_bun//bun:darwin_aarch64_toolchain",
"@rules_bun//bun:darwin_x64_toolchain",
"@rules_bun//bun:linux_aarch64_toolchain",
"@rules_bun//bun:linux_x64_toolchain",
"@rules_bun//bun:windows_x64_toolchain",
)

631
MODULE.bazel.lock generated Normal file
View File

@@ -0,0 +1,631 @@
{
"lockFileVersion": 26,
"registryFileHashes": {
"https://bcr.bazel.build/bazel_registry.json": "8a28e4aff06ee60aed2a8c281907fb8bcbf3b753c91fb5a5c57da3215d5b3497",
"https://bcr.bazel.build/modules/abseil-cpp/20210324.2/MODULE.bazel": "7cd0312e064fde87c8d1cd79ba06c876bd23630c83466e9500321be55c96ace2",
"https://bcr.bazel.build/modules/abseil-cpp/20211102.0/MODULE.bazel": "70390338f7a5106231d20620712f7cccb659cd0e9d073d1991c038eb9fc57589",
"https://bcr.bazel.build/modules/abseil-cpp/20230125.1/MODULE.bazel": "89047429cb0207707b2dface14ba7f8df85273d484c2572755be4bab7ce9c3a0",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0.bcr.1/MODULE.bazel": "1c8cec495288dccd14fdae6e3f95f772c1c91857047a098fad772034264cc8cb",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.0/MODULE.bazel": "d253ae36a8bd9ee3c5955384096ccb6baf16a1b1e93e858370da0a3b94f77c16",
"https://bcr.bazel.build/modules/abseil-cpp/20230802.1/MODULE.bazel": "fa92e2eb41a04df73cdabeec37107316f7e5272650f81d6cc096418fe647b915",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.1/MODULE.bazel": "37bcdb4440fbb61df6a1c296ae01b327f19e9bb521f9b8e26ec854b6f97309ed",
"https://bcr.bazel.build/modules/abseil-cpp/20240116.2/MODULE.bazel": "73939767a4686cd9a520d16af5ab440071ed75cec1a876bf2fcfaf1f71987a16",
"https://bcr.bazel.build/modules/abseil-cpp/20250127.1/MODULE.bazel": "c4a89e7ceb9bf1e25cf84a9f830ff6b817b72874088bf5141b314726e46a57c1",
"https://bcr.bazel.build/modules/abseil-cpp/20250512.1/MODULE.bazel": "d209fdb6f36ffaf61c509fcc81b19e81b411a999a934a032e10cd009a0226215",
"https://bcr.bazel.build/modules/abseil-cpp/20250814.1/MODULE.bazel": "51f2312901470cdab0dbdf3b88c40cd21c62a7ed58a3de45b365ddc5b11bcab2",
"https://bcr.bazel.build/modules/abseil-cpp/20250814.1/source.json": "cea3901d7e299da7320700abbaafe57a65d039f10d0d7ea601c4a66938ea4b0c",
"https://bcr.bazel.build/modules/apple_support/1.11.1/MODULE.bazel": "1843d7cd8a58369a444fc6000e7304425fba600ff641592161d9f15b179fb896",
"https://bcr.bazel.build/modules/apple_support/1.15.1/MODULE.bazel": "a0556fefca0b1bb2de8567b8827518f94db6a6e7e7d632b4c48dc5f865bc7c85",
"https://bcr.bazel.build/modules/apple_support/1.21.0/MODULE.bazel": "ac1824ed5edf17dee2fdd4927ada30c9f8c3b520be1b5fd02a5da15bc10bff3e",
"https://bcr.bazel.build/modules/apple_support/1.21.1/MODULE.bazel": "5809fa3efab15d1f3c3c635af6974044bac8a4919c62238cce06acee8a8c11f1",
"https://bcr.bazel.build/modules/apple_support/1.24.2/MODULE.bazel": "0e62471818affb9f0b26f128831d5c40b074d32e6dda5a0d3852847215a41ca4",
"https://bcr.bazel.build/modules/apple_support/1.24.2/source.json": "2c22c9827093250406c5568da6c54e6fdf0ef06238def3d99c71b12feb057a8d",
"https://bcr.bazel.build/modules/bazel_features/1.1.0/MODULE.bazel": "cfd42ff3b815a5f39554d97182657f8c4b9719568eb7fded2b9135f084bf760b",
"https://bcr.bazel.build/modules/bazel_features/1.1.1/MODULE.bazel": "27b8c79ef57efe08efccbd9dd6ef70d61b4798320b8d3c134fd571f78963dbcd",
"https://bcr.bazel.build/modules/bazel_features/1.10.0/MODULE.bazel": "f75e8807570484a99be90abcd52b5e1f390362c258bcb73106f4544957a48101",
"https://bcr.bazel.build/modules/bazel_features/1.11.0/MODULE.bazel": "f9382337dd5a474c3b7d334c2f83e50b6eaedc284253334cf823044a26de03e8",
"https://bcr.bazel.build/modules/bazel_features/1.15.0/MODULE.bazel": "d38ff6e517149dc509406aca0db3ad1efdd890a85e049585b7234d04238e2a4d",
"https://bcr.bazel.build/modules/bazel_features/1.17.0/MODULE.bazel": "039de32d21b816b47bd42c778e0454217e9c9caac4a3cf8e15c7231ee3ddee4d",
"https://bcr.bazel.build/modules/bazel_features/1.18.0/MODULE.bazel": "1be0ae2557ab3a72a57aeb31b29be347bcdc5d2b1eb1e70f39e3851a7e97041a",
"https://bcr.bazel.build/modules/bazel_features/1.19.0/MODULE.bazel": "59adcdf28230d220f0067b1f435b8537dd033bfff8db21335ef9217919c7fb58",
"https://bcr.bazel.build/modules/bazel_features/1.21.0/MODULE.bazel": "675642261665d8eea09989aa3b8afb5c37627f1be178382c320d1b46afba5e3b",
"https://bcr.bazel.build/modules/bazel_features/1.23.0/MODULE.bazel": "fd1ac84bc4e97a5a0816b7fd7d4d4f6d837b0047cf4cbd81652d616af3a6591a",
"https://bcr.bazel.build/modules/bazel_features/1.27.0/MODULE.bazel": "621eeee06c4458a9121d1f104efb80f39d34deff4984e778359c60eaf1a8cb65",
"https://bcr.bazel.build/modules/bazel_features/1.28.0/MODULE.bazel": "4b4200e6cbf8fa335b2c3f43e1d6ef3e240319c33d43d60cc0fbd4b87ece299d",
"https://bcr.bazel.build/modules/bazel_features/1.3.0/MODULE.bazel": "cdcafe83ec318cda34e02948e81d790aab8df7a929cec6f6969f13a489ccecd9",
"https://bcr.bazel.build/modules/bazel_features/1.30.0/MODULE.bazel": "a14b62d05969a293b80257e72e597c2da7f717e1e69fa8b339703ed6731bec87",
"https://bcr.bazel.build/modules/bazel_features/1.33.0/MODULE.bazel": "8b8dc9d2a4c88609409c3191165bccec0e4cb044cd7a72ccbe826583303459f6",
"https://bcr.bazel.build/modules/bazel_features/1.36.0/MODULE.bazel": "596cb62090b039caf1cad1d52a8bc35cf188ca9a4e279a828005e7ee49a1bec3",
"https://bcr.bazel.build/modules/bazel_features/1.4.1/MODULE.bazel": "e45b6bb2350aff3e442ae1111c555e27eac1d915e77775f6fdc4b351b758b5d7",
"https://bcr.bazel.build/modules/bazel_features/1.42.1/MODULE.bazel": "275a59b5406ff18c01739860aa70ad7ccb3cfb474579411decca11c93b951080",
"https://bcr.bazel.build/modules/bazel_features/1.42.1/source.json": "fcd4396b2df85f64f2b3bb436ad870793ecf39180f1d796f913cc9276d355309",
"https://bcr.bazel.build/modules/bazel_features/1.9.1/MODULE.bazel": "8f679097876a9b609ad1f60249c49d68bfab783dd9be012faf9d82547b14815a",
"https://bcr.bazel.build/modules/bazel_skylib/1.0.3/MODULE.bazel": "bcb0fd896384802d1ad283b4e4eb4d718eebd8cb820b0a2c3a347fb971afd9d8",
"https://bcr.bazel.build/modules/bazel_skylib/1.1.1/MODULE.bazel": "1add3e7d93ff2e6998f9e118022c84d163917d912f5afafb3058e3d2f1545b5e",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.0/MODULE.bazel": "44fe84260e454ed94ad326352a698422dbe372b21a1ac9f3eab76eb531223686",
"https://bcr.bazel.build/modules/bazel_skylib/1.2.1/MODULE.bazel": "f35baf9da0efe45fa3da1696ae906eea3d615ad41e2e3def4aeb4e8bc0ef9a7a",
"https://bcr.bazel.build/modules/bazel_skylib/1.3.0/MODULE.bazel": "20228b92868bf5cfc41bda7afc8a8ba2a543201851de39d990ec957b513579c5",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.1/MODULE.bazel": "a0dcb779424be33100dcae821e9e27e4f2901d9dfd5333efe5ac6a8d7ab75e1d",
"https://bcr.bazel.build/modules/bazel_skylib/1.4.2/MODULE.bazel": "3bd40978e7a1fac911d5989e6b09d8f64921865a45822d8b09e815eaa726a651",
"https://bcr.bazel.build/modules/bazel_skylib/1.5.0/MODULE.bazel": "32880f5e2945ce6a03d1fbd588e9198c0a959bb42297b2cfaf1685b7bc32e138",
"https://bcr.bazel.build/modules/bazel_skylib/1.6.1/MODULE.bazel": "8fdee2dbaace6c252131c00e1de4b165dc65af02ea278476187765e1a617b917",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.0/MODULE.bazel": "0db596f4563de7938de764cc8deeabec291f55e8ec15299718b93c4423e9796d",
"https://bcr.bazel.build/modules/bazel_skylib/1.7.1/MODULE.bazel": "3120d80c5861aa616222ec015332e5f8d3171e062e3e804a2a0253e1be26e59b",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.1/MODULE.bazel": "88ade7293becda963e0e3ea33e7d54d3425127e0a326e0d17da085a5f1f03ff6",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/MODULE.bazel": "69ad6927098316848b34a9142bcc975e018ba27f08c4ff403f50c1b6e646ca67",
"https://bcr.bazel.build/modules/bazel_skylib/1.8.2/source.json": "34a3c8bcf233b835eb74be9d628899bb32999d3e0eadef1947a0a562a2b16ffb",
"https://bcr.bazel.build/modules/buildozer/8.5.1/MODULE.bazel": "a35d9561b3fc5b18797c330793e99e3b834a473d5fbd3d7d7634aafc9bdb6f8f",
"https://bcr.bazel.build/modules/buildozer/8.5.1/source.json": "e3386e6ff4529f2442800dee47ad28d3e6487f36a1f75ae39ae56c70f0cd2fbd",
"https://bcr.bazel.build/modules/gazelle/0.32.0/MODULE.bazel": "b499f58a5d0d3537f3cf5b76d8ada18242f64ec474d8391247438bf04f58c7b8",
"https://bcr.bazel.build/modules/gazelle/0.33.0/MODULE.bazel": "a13a0f279b462b784fb8dd52a4074526c4a2afe70e114c7d09066097a46b3350",
"https://bcr.bazel.build/modules/gazelle/0.34.0/MODULE.bazel": "abdd8ce4d70978933209db92e436deb3a8b737859e9354fb5fd11fb5c2004c8a",
"https://bcr.bazel.build/modules/gazelle/0.36.0/MODULE.bazel": "e375d5d6e9a6ca59b0cb38b0540bc9a05b6aa926d322f2de268ad267a2ee74c0",
"https://bcr.bazel.build/modules/gazelle/0.36.0/source.json": "0823f097b127e0201ae55d85647c94095edfe27db0431a7ae880dcab08dfaa04",
"https://bcr.bazel.build/modules/google_benchmark/1.8.2/MODULE.bazel": "a70cf1bba851000ba93b58ae2f6d76490a9feb74192e57ab8e8ff13c34ec50cb",
"https://bcr.bazel.build/modules/googletest/1.11.0/MODULE.bazel": "3a83f095183f66345ca86aa13c58b59f9f94a2f81999c093d4eeaa2d262d12f4",
"https://bcr.bazel.build/modules/googletest/1.14.0.bcr.1/MODULE.bazel": "22c31a561553727960057361aa33bf20fb2e98584bc4fec007906e27053f80c6",
"https://bcr.bazel.build/modules/googletest/1.14.0/MODULE.bazel": "cfbcbf3e6eac06ef9d85900f64424708cc08687d1b527f0ef65aa7517af8118f",
"https://bcr.bazel.build/modules/googletest/1.15.2/MODULE.bazel": "6de1edc1d26cafb0ea1a6ab3f4d4192d91a312fd2d360b63adaa213cd00b2108",
"https://bcr.bazel.build/modules/googletest/1.17.0/MODULE.bazel": "dbec758171594a705933a29fcf69293d2468c49ec1f2ebca65c36f504d72df46",
"https://bcr.bazel.build/modules/googletest/1.17.0/source.json": "38e4454b25fc30f15439c0378e57909ab1fd0a443158aa35aec685da727cd713",
"https://bcr.bazel.build/modules/jsoncpp/1.9.5/MODULE.bazel": "31271aedc59e815656f5736f282bb7509a97c7ecb43e927ac1a37966e0578075",
"https://bcr.bazel.build/modules/jsoncpp/1.9.6/MODULE.bazel": "2f8d20d3b7d54143213c4dfc3d98225c42de7d666011528dc8fe91591e2e17b0",
"https://bcr.bazel.build/modules/jsoncpp/1.9.6/source.json": "a04756d367a2126c3541682864ecec52f92cdee80a35735a3cb249ce015ca000",
"https://bcr.bazel.build/modules/libpfm/4.11.0/MODULE.bazel": "45061ff025b301940f1e30d2c16bea596c25b176c8b6b3087e92615adbd52902",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/MODULE.bazel": "6f7b417dcc794d9add9e556673ad25cb3ba835224290f4f848f8e2db1e1fca74",
"https://bcr.bazel.build/modules/nlohmann_json/3.6.1/source.json": "f448c6e8963fdfa7eb831457df83ad63d3d6355018f6574fb017e8169deb43a9",
"https://bcr.bazel.build/modules/platforms/0.0.10/MODULE.bazel": "8cb8efaf200bdeb2150d93e162c40f388529a25852b332cec879373771e48ed5",
"https://bcr.bazel.build/modules/platforms/0.0.11/MODULE.bazel": "0daefc49732e227caa8bfa834d65dc52e8cc18a2faf80df25e8caea151a9413f",
"https://bcr.bazel.build/modules/platforms/0.0.4/MODULE.bazel": "9b328e31ee156f53f3c416a64f8491f7eb731742655a47c9eec4703a71644aee",
"https://bcr.bazel.build/modules/platforms/0.0.5/MODULE.bazel": "5733b54ea419d5eaf7997054bb55f6a1d0b5ff8aedf0176fef9eea44f3acda37",
"https://bcr.bazel.build/modules/platforms/0.0.6/MODULE.bazel": "ad6eeef431dc52aefd2d77ed20a4b353f8ebf0f4ecdd26a807d2da5aa8cd0615",
"https://bcr.bazel.build/modules/platforms/0.0.7/MODULE.bazel": "72fd4a0ede9ee5c021f6a8dd92b503e089f46c227ba2813ff183b71616034814",
"https://bcr.bazel.build/modules/platforms/0.0.8/MODULE.bazel": "9f142c03e348f6d263719f5074b21ef3adf0b139ee4c5133e2aa35664da9eb2d",
"https://bcr.bazel.build/modules/platforms/0.0.9/MODULE.bazel": "4a87a60c927b56ddd67db50c89acaa62f4ce2a1d2149ccb63ffd871d5ce29ebc",
"https://bcr.bazel.build/modules/platforms/1.0.0/MODULE.bazel": "f05feb42b48f1b3c225e4ccf351f367be0371411a803198ec34a389fb22aa580",
"https://bcr.bazel.build/modules/platforms/1.0.0/source.json": "f4ff1fd412e0246fd38c82328eb209130ead81d62dcd5a9e40910f867f733d96",
"https://bcr.bazel.build/modules/protobuf/21.7/MODULE.bazel": "a5a29bb89544f9b97edce05642fac225a808b5b7be74038ea3640fae2f8e66a7",
"https://bcr.bazel.build/modules/protobuf/27.0/MODULE.bazel": "7873b60be88844a0a1d8f80b9d5d20cfbd8495a689b8763e76c6372998d3f64c",
"https://bcr.bazel.build/modules/protobuf/27.1/MODULE.bazel": "703a7b614728bb06647f965264967a8ef1c39e09e8f167b3ca0bb1fd80449c0d",
"https://bcr.bazel.build/modules/protobuf/29.0-rc2/MODULE.bazel": "6241d35983510143049943fc0d57937937122baf1b287862f9dc8590fc4c37df",
"https://bcr.bazel.build/modules/protobuf/29.0-rc3/MODULE.bazel": "33c2dfa286578573afc55a7acaea3cada4122b9631007c594bf0729f41c8de92",
"https://bcr.bazel.build/modules/protobuf/29.0/MODULE.bazel": "319dc8bf4c679ff87e71b1ccfb5a6e90a6dbc4693501d471f48662ac46d04e4e",
"https://bcr.bazel.build/modules/protobuf/29.1/MODULE.bazel": "557c3457560ff49e122ed76c0bc3397a64af9574691cb8201b4e46d4ab2ecb95",
"https://bcr.bazel.build/modules/protobuf/3.19.0/MODULE.bazel": "6b5fbb433f760a99a22b18b6850ed5784ef0e9928a72668b66e4d7ccd47db9b0",
"https://bcr.bazel.build/modules/protobuf/3.19.2/MODULE.bazel": "532ffe5f2186b69fdde039efe6df13ba726ff338c6bc82275ad433013fa10573",
"https://bcr.bazel.build/modules/protobuf/3.19.6/MODULE.bazel": "9233edc5e1f2ee276a60de3eaa47ac4132302ef9643238f23128fea53ea12858",
"https://bcr.bazel.build/modules/protobuf/32.1/MODULE.bazel": "89cd2866a9cb07fee9ff74c41ceace11554f32e0d849de4e23ac55515cfada4d",
"https://bcr.bazel.build/modules/protobuf/33.4/MODULE.bazel": "114775b816b38b6d0ca620450d6b02550c60ceedfdc8d9a229833b34a223dc42",
"https://bcr.bazel.build/modules/protobuf/33.4/source.json": "555f8686b4c7d6b5ba731fbea13bf656b4bfd9a7ff629c1d9d3f6e1d6155de79",
"https://bcr.bazel.build/modules/pybind11_bazel/2.11.1/MODULE.bazel": "88af1c246226d87e65be78ed49ecd1e6f5e98648558c14ce99176da041dc378e",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/MODULE.bazel": "e6f4c20442eaa7c90d7190d8dc539d0ab422f95c65a57cc59562170c58ae3d34",
"https://bcr.bazel.build/modules/pybind11_bazel/2.12.0/source.json": "6900fdc8a9e95866b8c0d4ad4aba4d4236317b5c1cd04c502df3f0d33afed680",
"https://bcr.bazel.build/modules/re2/2023-09-01/MODULE.bazel": "cb3d511531b16cfc78a225a9e2136007a48cf8a677e4264baeab57fe78a80206",
"https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/MODULE.bazel": "b4963dda9b31080be1905ef085ecd7dd6cd47c05c79b9cdf83ade83ab2ab271a",
"https://bcr.bazel.build/modules/re2/2024-07-02.bcr.1/source.json": "2ff292be6ef3340325ce8a045ecc326e92cbfab47c7cbab4bd85d28971b97ac4",
"https://bcr.bazel.build/modules/re2/2024-07-02/MODULE.bazel": "0eadc4395959969297cbcf31a249ff457f2f1d456228c67719480205aa306daa",
"https://bcr.bazel.build/modules/rules_android/0.1.1/MODULE.bazel": "48809ab0091b07ad0182defb787c4c5328bd3a278938415c00a7b69b50c4d3a8",
"https://bcr.bazel.build/modules/rules_android/0.1.1/source.json": "e6986b41626ee10bdc864937ffb6d6bf275bb5b9c65120e6137d56e6331f089e",
"https://bcr.bazel.build/modules/rules_apple/3.16.0/MODULE.bazel": "0d1caf0b8375942ce98ea944be754a18874041e4e0459401d925577624d3a54a",
"https://bcr.bazel.build/modules/rules_apple/4.1.0/MODULE.bazel": "76e10fd4a48038d3fc7c5dc6e63b7063bbf5304a2e3bd42edda6ec660eebea68",
"https://bcr.bazel.build/modules/rules_apple/4.1.0/source.json": "8ee81e1708756f81b343a5eb2b2f0b953f1d25c4ab3d4a68dc02754872e80715",
"https://bcr.bazel.build/modules/rules_cc/0.0.1/MODULE.bazel": "cb2aa0747f84c6c3a78dad4e2049c154f08ab9d166b1273835a8174940365647",
"https://bcr.bazel.build/modules/rules_cc/0.0.10/MODULE.bazel": "ec1705118f7eaedd6e118508d3d26deba2a4e76476ada7e0e3965211be012002",
"https://bcr.bazel.build/modules/rules_cc/0.0.13/MODULE.bazel": "0e8529ed7b323dad0775ff924d2ae5af7640b23553dfcd4d34344c7e7a867191",
"https://bcr.bazel.build/modules/rules_cc/0.0.15/MODULE.bazel": "6704c35f7b4a72502ee81f61bf88706b54f06b3cbe5558ac17e2e14666cd5dcc",
"https://bcr.bazel.build/modules/rules_cc/0.0.16/MODULE.bazel": "7661303b8fc1b4d7f532e54e9d6565771fea666fbdf839e0a86affcd02defe87",
"https://bcr.bazel.build/modules/rules_cc/0.0.17/MODULE.bazel": "2ae1d8f4238ec67d7185d8861cb0a2cdf4bc608697c331b95bf990e69b62e64a",
"https://bcr.bazel.build/modules/rules_cc/0.0.2/MODULE.bazel": "6915987c90970493ab97393024c156ea8fb9f3bea953b2f3ec05c34f19b5695c",
"https://bcr.bazel.build/modules/rules_cc/0.0.6/MODULE.bazel": "abf360251023dfe3efcef65ab9d56beefa8394d4176dd29529750e1c57eaa33f",
"https://bcr.bazel.build/modules/rules_cc/0.0.8/MODULE.bazel": "964c85c82cfeb6f3855e6a07054fdb159aced38e99a5eecf7bce9d53990afa3e",
"https://bcr.bazel.build/modules/rules_cc/0.0.9/MODULE.bazel": "836e76439f354b89afe6a911a7adf59a6b2518fafb174483ad78a2a2fde7b1c5",
"https://bcr.bazel.build/modules/rules_cc/0.1.1/MODULE.bazel": "2f0222a6f229f0bf44cd711dc13c858dad98c62d52bd51d8fc3a764a83125513",
"https://bcr.bazel.build/modules/rules_cc/0.1.2/MODULE.bazel": "557ddc3a96858ec0d465a87c0a931054d7dcfd6583af2c7ed3baf494407fd8d0",
"https://bcr.bazel.build/modules/rules_cc/0.1.5/MODULE.bazel": "88dfc9361e8b5ae1008ac38f7cdfd45ad738e4fa676a3ad67d19204f045a1fd8",
"https://bcr.bazel.build/modules/rules_cc/0.2.0/MODULE.bazel": "b5c17f90458caae90d2ccd114c81970062946f49f355610ed89bebf954f5783c",
"https://bcr.bazel.build/modules/rules_cc/0.2.13/MODULE.bazel": "eecdd666eda6be16a8d9dc15e44b5c75133405e820f620a234acc4b1fdc5aa37",
"https://bcr.bazel.build/modules/rules_cc/0.2.17/MODULE.bazel": "1849602c86cb60da8613d2de887f9566a6d354a6df6d7009f9d04a14402f9a84",
"https://bcr.bazel.build/modules/rules_cc/0.2.17/source.json": "3832f45d145354049137c0090df04629d9c2b5493dc5c2bf46f1834040133a07",
"https://bcr.bazel.build/modules/rules_cc/0.2.8/MODULE.bazel": "f1df20f0bf22c28192a794f29b501ee2018fa37a3862a1a2132ae2940a23a642",
"https://bcr.bazel.build/modules/rules_foreign_cc/0.9.0/MODULE.bazel": "c9e8c682bf75b0e7c704166d79b599f93b72cfca5ad7477df596947891feeef6",
"https://bcr.bazel.build/modules/rules_fuzzing/0.5.2/MODULE.bazel": "40c97d1144356f52905566c55811f13b299453a14ac7769dfba2ac38192337a8",
"https://bcr.bazel.build/modules/rules_go/0.41.0/MODULE.bazel": "55861d8e8bb0e62cbd2896f60ff303f62ffcb0eddb74ecb0e5c0cbe36fc292c8",
"https://bcr.bazel.build/modules/rules_go/0.42.0/MODULE.bazel": "8cfa875b9aa8c6fce2b2e5925e73c1388173ea3c32a0db4d2b4804b453c14270",
"https://bcr.bazel.build/modules/rules_go/0.46.0/MODULE.bazel": "3477df8bdcc49e698b9d25f734c4f3a9f5931ff34ee48a2c662be168f5f2d3fd",
"https://bcr.bazel.build/modules/rules_go/0.60.0/MODULE.bazel": "4a57ff2ffc2a3570e3c5646575c5a4b07287e91bcdac5d1f72383d51502b48cb",
"https://bcr.bazel.build/modules/rules_go/0.60.0/source.json": "1e21368c5e0c3013a110bd79a8fcff8ca46b5bcb2b561713a7273cbfcff7c464",
"https://bcr.bazel.build/modules/rules_java/4.0.0/MODULE.bazel": "5a78a7ae82cd1a33cef56dc578c7d2a46ed0dca12643ee45edbb8417899e6f74",
"https://bcr.bazel.build/modules/rules_java/5.3.5/MODULE.bazel": "a4ec4f2db570171e3e5eb753276ee4b389bae16b96207e9d3230895c99644b86",
"https://bcr.bazel.build/modules/rules_java/6.5.2/MODULE.bazel": "1d440d262d0e08453fa0c4d8f699ba81609ed0e9a9a0f02cd10b3e7942e61e31",
"https://bcr.bazel.build/modules/rules_java/7.10.0/MODULE.bazel": "530c3beb3067e870561739f1144329a21c851ff771cd752a49e06e3dc9c2e71a",
"https://bcr.bazel.build/modules/rules_java/7.12.2/MODULE.bazel": "579c505165ee757a4280ef83cda0150eea193eed3bef50b1004ba88b99da6de6",
"https://bcr.bazel.build/modules/rules_java/7.2.0/MODULE.bazel": "06c0334c9be61e6cef2c8c84a7800cef502063269a5af25ceb100b192453d4ab",
"https://bcr.bazel.build/modules/rules_java/7.6.1/MODULE.bazel": "2f14b7e8a1aa2f67ae92bc69d1ec0fa8d9f827c4e17ff5e5f02e91caa3b2d0fe",
"https://bcr.bazel.build/modules/rules_java/8.3.2/MODULE.bazel": "7336d5511ad5af0b8615fdc7477535a2e4e723a357b6713af439fe8cf0195017",
"https://bcr.bazel.build/modules/rules_java/8.5.1/MODULE.bazel": "d8a9e38cc5228881f7055a6079f6f7821a073df3744d441978e7a43e20226939",
"https://bcr.bazel.build/modules/rules_java/8.6.1/MODULE.bazel": "f4808e2ab5b0197f094cabce9f4b006a27766beb6a9975931da07099560ca9c2",
"https://bcr.bazel.build/modules/rules_java/9.0.3/MODULE.bazel": "1f98ed015f7e744a745e0df6e898a7c5e83562d6b759dfd475c76456dda5ccea",
"https://bcr.bazel.build/modules/rules_java/9.0.3/source.json": "b038c0c07e12e658135bbc32cc1a2ded6e33785105c9d41958014c592de4593e",
"https://bcr.bazel.build/modules/rules_jvm_external/4.4.2/MODULE.bazel": "a56b85e418c83eb1839819f0b515c431010160383306d13ec21959ac412d2fe7",
"https://bcr.bazel.build/modules/rules_jvm_external/5.1/MODULE.bazel": "33f6f999e03183f7d088c9be518a63467dfd0be94a11d0055fe2d210f89aa909",
"https://bcr.bazel.build/modules/rules_jvm_external/5.2/MODULE.bazel": "d9351ba35217ad0de03816ef3ed63f89d411349353077348a45348b096615036",
"https://bcr.bazel.build/modules/rules_jvm_external/6.3/MODULE.bazel": "c998e060b85f71e00de5ec552019347c8bca255062c990ac02d051bb80a38df0",
"https://bcr.bazel.build/modules/rules_jvm_external/6.7/MODULE.bazel": "e717beabc4d091ecb2c803c2d341b88590e9116b8bf7947915eeb33aab4f96dd",
"https://bcr.bazel.build/modules/rules_jvm_external/6.7/source.json": "5426f412d0a7fc6b611643376c7e4a82dec991491b9ce5cb1cfdd25fe2e92be4",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/MODULE.bazel": "d269a01a18ee74d0335450b10f62c9ed81f2321d7958a2934e44272fe82dcef3",
"https://bcr.bazel.build/modules/rules_kotlin/1.9.6/source.json": "2faa4794364282db7c06600b7e5e34867a564ae91bda7cae7c29c64e9466b7d5",
"https://bcr.bazel.build/modules/rules_license/0.0.3/MODULE.bazel": "627e9ab0247f7d1e05736b59dbb1b6871373de5ad31c3011880b4133cafd4bd0",
"https://bcr.bazel.build/modules/rules_license/0.0.7/MODULE.bazel": "088fbeb0b6a419005b89cf93fe62d9517c0a2b8bb56af3244af65ecfe37e7d5d",
"https://bcr.bazel.build/modules/rules_license/1.0.0/MODULE.bazel": "a7fda60eefdf3d8c827262ba499957e4df06f659330bbe6cdbdb975b768bb65c",
"https://bcr.bazel.build/modules/rules_license/1.0.0/source.json": "a52c89e54cc311196e478f8382df91c15f7a2bfdf4c6cd0e2675cc2ff0b56efb",
"https://bcr.bazel.build/modules/rules_pkg/0.7.0/MODULE.bazel": "df99f03fc7934a4737122518bb87e667e62d780b610910f0447665a7e2be62dc",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/MODULE.bazel": "5b1df97dbc29623bccdf2b0dcd0f5cb08e2f2c9050aab1092fd39a41e82686ff",
"https://bcr.bazel.build/modules/rules_pkg/1.0.1/source.json": "bd82e5d7b9ce2d31e380dd9f50c111d678c3bdaca190cb76b0e1c71b05e1ba8a",
"https://bcr.bazel.build/modules/rules_proto/4.0.0/MODULE.bazel": "a7a7b6ce9bee418c1a760b3d84f83a299ad6952f9903c67f19e4edd964894e06",
"https://bcr.bazel.build/modules/rules_proto/5.3.0-21.7/MODULE.bazel": "e8dff86b0971688790ae75528fe1813f71809b5afd57facb44dad9e8eca631b7",
"https://bcr.bazel.build/modules/rules_proto/6.0.0-rc1/MODULE.bazel": "1e5b502e2e1a9e825eef74476a5a1ee524a92297085015a052510b09a1a09483",
"https://bcr.bazel.build/modules/rules_proto/6.0.2/MODULE.bazel": "ce916b775a62b90b61888052a416ccdda405212b6aaeb39522f7dc53431a5e73",
"https://bcr.bazel.build/modules/rules_proto/7.0.2/MODULE.bazel": "bf81793bd6d2ad89a37a40693e56c61b0ee30f7a7fdbaf3eabbf5f39de47dea2",
"https://bcr.bazel.build/modules/rules_proto/7.1.0/MODULE.bazel": "002d62d9108f75bb807cd56245d45648f38275cb3a99dcd45dfb864c5d74cb96",
"https://bcr.bazel.build/modules/rules_proto/7.1.0/source.json": "39f89066c12c24097854e8f57ab8558929f9c8d474d34b2c00ac04630ad8940e",
"https://bcr.bazel.build/modules/rules_python/0.10.2/MODULE.bazel": "cc82bc96f2997baa545ab3ce73f196d040ffb8756fd2d66125a530031cd90e5f",
"https://bcr.bazel.build/modules/rules_python/0.23.1/MODULE.bazel": "49ffccf0511cb8414de28321f5fcf2a31312b47c40cc21577144b7447f2bf300",
"https://bcr.bazel.build/modules/rules_python/0.25.0/MODULE.bazel": "72f1506841c920a1afec76975b35312410eea3aa7b63267436bfb1dd91d2d382",
"https://bcr.bazel.build/modules/rules_python/0.28.0/MODULE.bazel": "cba2573d870babc976664a912539b320cbaa7114cd3e8f053c720171cde331ed",
"https://bcr.bazel.build/modules/rules_python/0.31.0/MODULE.bazel": "93a43dc47ee570e6ec9f5779b2e64c1476a6ce921c48cc9a1678a91dd5f8fd58",
"https://bcr.bazel.build/modules/rules_python/0.33.2/MODULE.bazel": "3e036c4ad8d804a4dad897d333d8dce200d943df4827cb849840055be8d2e937",
"https://bcr.bazel.build/modules/rules_python/0.4.0/MODULE.bazel": "9208ee05fd48bf09ac60ed269791cf17fb343db56c8226a720fbb1cdf467166c",
"https://bcr.bazel.build/modules/rules_python/1.3.0/MODULE.bazel": "8361d57eafb67c09b75bf4bbe6be360e1b8f4f18118ab48037f2bd50aa2ccb13",
"https://bcr.bazel.build/modules/rules_python/1.4.1/MODULE.bazel": "8991ad45bdc25018301d6b7e1d3626afc3c8af8aaf4bc04f23d0b99c938b73a6",
"https://bcr.bazel.build/modules/rules_python/1.6.0/MODULE.bazel": "7e04ad8f8d5bea40451cf80b1bd8262552aa73f841415d20db96b7241bd027d8",
"https://bcr.bazel.build/modules/rules_python/1.7.0/MODULE.bazel": "d01f995ecd137abf30238ad9ce97f8fc3ac57289c8b24bd0bf53324d937a14f8",
"https://bcr.bazel.build/modules/rules_python/1.7.0/source.json": "028a084b65dcf8f4dc4f82f8778dbe65df133f234b316828a82e060d81bdce32",
"https://bcr.bazel.build/modules/rules_shell/0.2.0/MODULE.bazel": "fda8a652ab3c7d8fee214de05e7a9916d8b28082234e8d2c0094505c5268ed3c",
"https://bcr.bazel.build/modules/rules_shell/0.3.0/MODULE.bazel": "de4402cd12f4cc8fda2354fce179fdb068c0b9ca1ec2d2b17b3e21b24c1a937b",
"https://bcr.bazel.build/modules/rules_shell/0.6.1/MODULE.bazel": "72e76b0eea4e81611ef5452aa82b3da34caca0c8b7b5c0c9584338aa93bae26b",
"https://bcr.bazel.build/modules/rules_shell/0.6.1/source.json": "20ec05cd5e592055e214b2da8ccb283c7f2a421ea0dc2acbf1aa792e11c03d0c",
"https://bcr.bazel.build/modules/rules_swift/1.16.0/MODULE.bazel": "4a09f199545a60d09895e8281362b1ff3bb08bbde69c6fc87aff5b92fcc916ca",
"https://bcr.bazel.build/modules/rules_swift/2.1.1/MODULE.bazel": "494900a80f944fc7aa61500c2073d9729dff0b764f0e89b824eb746959bc1046",
"https://bcr.bazel.build/modules/rules_swift/2.4.0/MODULE.bazel": "1639617eb1ede28d774d967a738b4a68b0accb40650beadb57c21846beab5efd",
"https://bcr.bazel.build/modules/rules_swift/3.1.2/MODULE.bazel": "72c8f5cf9d26427cee6c76c8e3853eb46ce6b0412a081b2b6db6e8ad56267400",
"https://bcr.bazel.build/modules/rules_swift/3.1.2/source.json": "e85761f3098a6faf40b8187695e3de6d97944e98abd0d8ce579cb2daf6319a66",
"https://bcr.bazel.build/modules/stardoc/0.5.1/MODULE.bazel": "1a05d92974d0c122f5ccf09291442580317cdd859f07a8655f1db9a60374f9f8",
"https://bcr.bazel.build/modules/stardoc/0.5.3/MODULE.bazel": "c7f6948dae6999bf0db32c1858ae345f112cacf98f174c7a8bb707e41b974f1c",
"https://bcr.bazel.build/modules/stardoc/0.7.0/MODULE.bazel": "05e3d6d30c099b6770e97da986c53bd31844d7f13d41412480ea265ac9e8079c",
"https://bcr.bazel.build/modules/stardoc/0.7.2/MODULE.bazel": "fc152419aa2ea0f51c29583fab1e8c99ddefd5b3778421845606ee628629e0e5",
"https://bcr.bazel.build/modules/stardoc/0.7.2/source.json": "58b029e5e901d6802967754adf0a9056747e8176f017cfe3607c0851f4d42216",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.1/MODULE.bazel": "5e463fbfba7b1701d957555ed45097d7f984211330106ccd1352c6e0af0dcf91",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/MODULE.bazel": "75aab2373a4bbe2a1260b9bf2a1ebbdbf872d3bd36f80bff058dccd82e89422f",
"https://bcr.bazel.build/modules/swift_argument_parser/1.3.1.2/source.json": "5fba48bbe0ba48761f9e9f75f92876cafb5d07c0ce059cc7a8027416de94a05b",
"https://bcr.bazel.build/modules/upb/0.0.0-20220923-a547704/MODULE.bazel": "7298990c00040a0e2f121f6c32544bab27d4452f80d9ce51349b1a28f3005c43",
"https://bcr.bazel.build/modules/zlib/1.2.11/MODULE.bazel": "07b389abc85fdbca459b69e2ec656ae5622873af3f845e1c9d80fe179f3effa0",
"https://bcr.bazel.build/modules/zlib/1.2.12/MODULE.bazel": "3b1a8834ada2a883674be8cbd36ede1b6ec481477ada359cd2d3ddc562340b27",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/MODULE.bazel": "eec517b5bbe5492629466e11dae908d043364302283de25581e3eb944326c4ca",
"https://bcr.bazel.build/modules/zlib/1.3.1.bcr.5/source.json": "22bc55c47af97246cfc093d0acf683a7869377de362b5d1c552c2c2e16b7a806",
"https://bcr.bazel.build/modules/zlib/1.3.1/MODULE.bazel": "751c9940dcfe869f5f7274e1295422a34623555916eb98c174c1e945594bf198"
},
"selectedYankedVersions": {},
"moduleExtensions": {
"@@rules_kotlin+//src/main/starlark/core/repositories:bzlmod_setup.bzl%rules_kotlin_extensions": {
"general": {
"bzlTransitiveDigest": "ABI1D/sbS1ovwaW/kHDoj8nnXjQ0oKU9fzmzEG4iT8o=",
"usagesDigest": "QI2z8ZUR+mqtbwsf2fLqYdJAkPOHdOV+tF2yVAUgRzw=",
"recordedInputs": [
"REPO_MAPPING:rules_kotlin+,bazel_tools bazel_tools"
],
"generatedRepoSpecs": {
"com_github_jetbrains_kotlin_git": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_compiler_git_repository",
"attributes": {
"urls": [
"https://github.com/JetBrains/kotlin/releases/download/v1.9.23/kotlin-compiler-1.9.23.zip"
],
"sha256": "93137d3aab9afa9b27cb06a824c2324195c6b6f6179d8a8653f440f5bd58be88"
}
},
"com_github_jetbrains_kotlin": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:compiler.bzl%kotlin_capabilities_repository",
"attributes": {
"git_repository_name": "com_github_jetbrains_kotlin_git",
"compiler_version": "1.9.23"
}
},
"com_github_google_ksp": {
"repoRuleId": "@@rules_kotlin+//src/main/starlark/core/repositories:ksp.bzl%ksp_compiler_plugin_repository",
"attributes": {
"urls": [
"https://github.com/google/ksp/releases/download/1.9.23-1.0.20/artifacts.zip"
],
"sha256": "ee0618755913ef7fd6511288a232e8fad24838b9af6ea73972a76e81053c8c2d",
"strip_version": "1.9.23-1.0.20"
}
},
"com_github_pinterest_ktlint": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_file",
"attributes": {
"sha256": "01b2e0ef893383a50dbeb13970fe7fa3be36ca3e83259e01649945b09d736985",
"urls": [
"https://github.com/pinterest/ktlint/releases/download/1.3.0/ktlint"
],
"executable": true
}
},
"rules_android": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"sha256": "cd06d15dd8bb59926e4d65f9003bfc20f9da4b2519985c27e190cddc8b7a7806",
"strip_prefix": "rules_android-0.1.1",
"urls": [
"https://github.com/bazelbuild/rules_android/archive/v0.1.1.zip"
]
}
}
}
}
},
"@@rules_python+//python/extensions:config.bzl%config": {
"general": {
"bzlTransitiveDigest": "2hLgIvNVTLgxus0ZuXtleBe70intCfo0cHs8qvt6cdM=",
"usagesDigest": "ZVSXMAGpD+xzVNPuvF1IoLBkty7TROO0+akMapt1pAg=",
"recordedInputs": [
"REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
"REPO_MAPPING:rules_python+,pypi__build rules_python++config+pypi__build",
"REPO_MAPPING:rules_python+,pypi__click rules_python++config+pypi__click",
"REPO_MAPPING:rules_python+,pypi__colorama rules_python++config+pypi__colorama",
"REPO_MAPPING:rules_python+,pypi__importlib_metadata rules_python++config+pypi__importlib_metadata",
"REPO_MAPPING:rules_python+,pypi__installer rules_python++config+pypi__installer",
"REPO_MAPPING:rules_python+,pypi__more_itertools rules_python++config+pypi__more_itertools",
"REPO_MAPPING:rules_python+,pypi__packaging rules_python++config+pypi__packaging",
"REPO_MAPPING:rules_python+,pypi__pep517 rules_python++config+pypi__pep517",
"REPO_MAPPING:rules_python+,pypi__pip rules_python++config+pypi__pip",
"REPO_MAPPING:rules_python+,pypi__pip_tools rules_python++config+pypi__pip_tools",
"REPO_MAPPING:rules_python+,pypi__pyproject_hooks rules_python++config+pypi__pyproject_hooks",
"REPO_MAPPING:rules_python+,pypi__setuptools rules_python++config+pypi__setuptools",
"REPO_MAPPING:rules_python+,pypi__tomli rules_python++config+pypi__tomli",
"REPO_MAPPING:rules_python+,pypi__wheel rules_python++config+pypi__wheel",
"REPO_MAPPING:rules_python+,pypi__zipp rules_python++config+pypi__zipp"
],
"generatedRepoSpecs": {
"rules_python_internal": {
"repoRuleId": "@@rules_python+//python/private:internal_config_repo.bzl%internal_config_repo",
"attributes": {
"transition_setting_generators": {},
"transition_settings": []
}
},
"pypi__build": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/e2/03/f3c8ba0a6b6e30d7d18c40faab90807c9bb5e9a1e3b2fe2008af624a9c97/build-1.2.1-py3-none-any.whl",
"sha256": "75e10f767a433d9a86e50d83f418e83efc18ede923ee5ff7df93b6cb0306c5d4",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__click": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl",
"sha256": "ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__colorama": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl",
"sha256": "4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__importlib_metadata": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/2d/0a/679461c511447ffaf176567d5c496d1de27cbe34a87df6677d7171b2fbd4/importlib_metadata-7.1.0-py3-none-any.whl",
"sha256": "30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__installer": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/e5/ca/1172b6638d52f2d6caa2dd262ec4c811ba59eee96d54a7701930726bce18/installer-0.7.0-py3-none-any.whl",
"sha256": "05d1933f0a5ba7d8d6296bb6d5018e7c94fa473ceb10cf198a92ccea19c27b53",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__more_itertools": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/50/e2/8e10e465ee3987bb7c9ab69efb91d867d93959095f4807db102d07995d94/more_itertools-10.2.0-py3-none-any.whl",
"sha256": "686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__packaging": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/49/df/1fceb2f8900f8639e278b056416d49134fb8d84c5942ffaa01ad34782422/packaging-24.0-py3-none-any.whl",
"sha256": "2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pep517": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/25/6e/ca4a5434eb0e502210f591b97537d322546e4833dcb4d470a48c375c5540/pep517-0.13.1-py3-none-any.whl",
"sha256": "31b206f67165b3536dd577c5c3f1518e8fbaf38cbc57efff8369a392feff1721",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pip": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/8a/6a/19e9fe04fca059ccf770861c7d5721ab4c2aebc539889e97c7977528a53b/pip-24.0-py3-none-any.whl",
"sha256": "ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pip_tools": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/0d/dc/38f4ce065e92c66f058ea7a368a9c5de4e702272b479c0992059f7693941/pip_tools-7.4.1-py3-none-any.whl",
"sha256": "4c690e5fbae2f21e87843e89c26191f0d9454f362d8acdbd695716493ec8b3a9",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__pyproject_hooks": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/ae/f3/431b9d5fe7d14af7a32340792ef43b8a714e7726f1d7b69cc4e8e7a3f1d7/pyproject_hooks-1.1.0-py3-none-any.whl",
"sha256": "7ceeefe9aec63a1064c18d939bdc3adf2d8aa1988a510afec15151578b232aa2",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__setuptools": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl",
"sha256": "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__tomli": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/97/75/10a9ebee3fd790d20926a90a2547f0bf78f371b2f13aa822c759680ca7b9/tomli-2.0.1-py3-none-any.whl",
"sha256": "939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__wheel": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/7d/cd/d7460c9a869b16c3dd4e1e403cce337df165368c71d6af229a74699622ce/wheel-0.43.0-py3-none-any.whl",
"sha256": "55c570405f142630c6b9f72fe09d9b67cf1477fcf543ae5b8dcb1f5b7377da81",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
},
"pypi__zipp": {
"repoRuleId": "@@bazel_tools//tools/build_defs/repo:http.bzl%http_archive",
"attributes": {
"url": "https://files.pythonhosted.org/packages/da/55/a03fd7240714916507e1fcf7ae355bd9d9ed2e6db492595f1a67f61681be/zipp-3.18.2-py3-none-any.whl",
"sha256": "dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e",
"type": "zip",
"build_file_content": "package(default_visibility = [\"//visibility:public\"])\n\nload(\"@rules_python//python:py_library.bzl\", \"py_library\")\n\npy_library(\n name = \"lib\",\n srcs = glob([\"**/*.py\"]),\n data = glob([\"**/*\"], exclude=[\n # These entries include those put into user-installed dependencies by\n # data_exclude to avoid non-determinism.\n \"**/*.py\",\n \"**/*.pyc\",\n \"**/*.pyc.*\", # During pyc creation, temp files named *.pyc.NNN are created\n \"**/*.dist-info/RECORD\",\n \"BUILD\",\n \"WORKSPACE\",\n ]),\n # This makes this directory a top-level in the python import\n # search path for anything that depends on this.\n imports = [\".\"],\n)\n"
}
}
}
}
},
"@@rules_python+//python/uv:uv.bzl%uv": {
"general": {
"bzlTransitiveDigest": "ijW9KS7qsIY+yBVvJ+Nr1mzwQox09j13DnE3iIwaeTM=",
"usagesDigest": "H8dQoNZcoqP+Mu0tHZTi4KHATzvNkM5ePuEqoQdklIU=",
"recordedInputs": [
"REPO_MAPPING:rules_python+,bazel_tools bazel_tools",
"REPO_MAPPING:rules_python+,platforms platforms"
],
"generatedRepoSpecs": {
"uv": {
"repoRuleId": "@@rules_python+//python/uv/private:uv_toolchains_repo.bzl%uv_toolchains_repo",
"attributes": {
"toolchain_type": "'@@rules_python+//python/uv:uv_toolchain_type'",
"toolchain_names": [
"none"
],
"toolchain_implementations": {
"none": "'@@rules_python+//python:none'"
},
"toolchain_compatible_with": {
"none": [
"@platforms//:incompatible"
]
},
"toolchain_target_settings": {}
}
}
}
}
}
},
"facts": {
"@@rules_go+//go:extensions.bzl%go_sdk": {
"1.25.0": {
"aix_ppc64": [
"go1.25.0.aix-ppc64.tar.gz",
"e5234a7dac67bc86c528fe9752fc9d63557918627707a733ab4cac1a6faed2d4"
],
"darwin_amd64": [
"go1.25.0.darwin-amd64.tar.gz",
"5bd60e823037062c2307c71e8111809865116714d6f6b410597cf5075dfd80ef"
],
"darwin_arm64": [
"go1.25.0.darwin-arm64.tar.gz",
"544932844156d8172f7a28f77f2ac9c15a23046698b6243f633b0a0b00c0749c"
],
"dragonfly_amd64": [
"go1.25.0.dragonfly-amd64.tar.gz",
"5ed3cf9a810a1483822538674f1336c06b51aa1b94d6d545a1a0319a48177120"
],
"freebsd_386": [
"go1.25.0.freebsd-386.tar.gz",
"abea5d5c6697e6b5c224731f2158fe87c602996a2a233ac0c4730cd57bf8374e"
],
"freebsd_amd64": [
"go1.25.0.freebsd-amd64.tar.gz",
"86e6fe0a29698d7601c4442052dac48bd58d532c51cccb8f1917df648138730b"
],
"freebsd_arm": [
"go1.25.0.freebsd-arm.tar.gz",
"d90b78e41921f72f30e8bbc81d9dec2cff7ff384a33d8d8debb24053e4336bfe"
],
"freebsd_arm64": [
"go1.25.0.freebsd-arm64.tar.gz",
"451d0da1affd886bfb291b7c63a6018527b269505db21ce6e14724f22ab0662e"
],
"freebsd_riscv64": [
"go1.25.0.freebsd-riscv64.tar.gz",
"7b565f76bd8bda46549eeaaefe0e53b251e644c230577290c0f66b1ecdb3cdbe"
],
"illumos_amd64": [
"go1.25.0.illumos-amd64.tar.gz",
"b1e1fdaab1ad25aa1c08d7a36c97d45d74b98b89c3f78c6d2145f77face54a2c"
],
"linux_386": [
"go1.25.0.linux-386.tar.gz",
"8c602dd9d99bc9453b3995d20ce4baf382cc50855900a0ece5de9929df4a993a"
],
"linux_amd64": [
"go1.25.0.linux-amd64.tar.gz",
"2852af0cb20a13139b3448992e69b868e50ed0f8a1e5940ee1de9e19a123b613"
],
"linux_arm64": [
"go1.25.0.linux-arm64.tar.gz",
"05de75d6994a2783699815ee553bd5a9327d8b79991de36e38b66862782f54ae"
],
"linux_armv6l": [
"go1.25.0.linux-armv6l.tar.gz",
"a5a8f8198fcf00e1e485b8ecef9ee020778bf32a408a4e8873371bfce458cd09"
],
"linux_loong64": [
"go1.25.0.linux-loong64.tar.gz",
"cab86b1cf761b1cb3bac86a8877cfc92e7b036fc0d3084123d77013d61432afc"
],
"linux_mips": [
"go1.25.0.linux-mips.tar.gz",
"d66b6fb74c3d91b9829dc95ec10ca1f047ef5e89332152f92e136cf0e2da5be1"
],
"linux_mips64": [
"go1.25.0.linux-mips64.tar.gz",
"4082e4381a8661bc2a839ff94ba3daf4f6cde20f8fb771b5b3d4762dc84198a2"
],
"linux_mips64le": [
"go1.25.0.linux-mips64le.tar.gz",
"70002c299ec7f7175ac2ef673b1b347eecfa54ae11f34416a6053c17f855afcc"
],
"linux_mipsle": [
"go1.25.0.linux-mipsle.tar.gz",
"b00a3a39eff099f6df9f1c7355bf28e4589d0586f42d7d4a394efb763d145a73"
],
"linux_ppc64": [
"go1.25.0.linux-ppc64.tar.gz",
"df166f33bd98160662560a72ff0b4ba731f969a80f088922bddcf566a88c1ec1"
],
"linux_ppc64le": [
"go1.25.0.linux-ppc64le.tar.gz",
"0f18a89e7576cf2c5fa0b487a1635d9bcbf843df5f110e9982c64df52a983ad0"
],
"linux_riscv64": [
"go1.25.0.linux-riscv64.tar.gz",
"c018ff74a2c48d55c8ca9b07c8e24163558ffec8bea08b326d6336905d956b67"
],
"linux_s390x": [
"go1.25.0.linux-s390x.tar.gz",
"34e5a2e19f2292fbaf8783e3a241e6e49689276aef6510a8060ea5ef54eee408"
],
"netbsd_386": [
"go1.25.0.netbsd-386.tar.gz",
"f8586cdb7aa855657609a5c5f6dbf523efa00c2bbd7c76d3936bec80aa6c0aba"
],
"netbsd_amd64": [
"go1.25.0.netbsd-amd64.tar.gz",
"ae8dc1469385b86a157a423bb56304ba45730de8a897615874f57dd096db2c2a"
],
"netbsd_arm": [
"go1.25.0.netbsd-arm.tar.gz",
"1ff7e4cc764425fc9dd6825eaee79d02b3c7cafffbb3691687c8d672ade76cb7"
],
"netbsd_arm64": [
"go1.25.0.netbsd-arm64.tar.gz",
"e1b310739f26724216aa6d7d7208c4031f9ff54c9b5b9a796ddc8bebcb4a5f16"
],
"openbsd_386": [
"go1.25.0.openbsd-386.tar.gz",
"4802a9b20e533da91adb84aab42e94aa56cfe3e5475d0550bed3385b182e69d8"
],
"openbsd_amd64": [
"go1.25.0.openbsd-amd64.tar.gz",
"c016cd984bebe317b19a4f297c4f50def120dc9788490540c89f28e42f1dabe1"
],
"openbsd_arm": [
"go1.25.0.openbsd-arm.tar.gz",
"a1e31d0bf22172ddde42edf5ec811ef81be43433df0948ece52fecb247ccfd8d"
],
"openbsd_arm64": [
"go1.25.0.openbsd-arm64.tar.gz",
"343ea8edd8c218196e15a859c6072d0dd3246fbbb168481ab665eb4c4140458d"
],
"openbsd_ppc64": [
"go1.25.0.openbsd-ppc64.tar.gz",
"694c14da1bcaeb5e3332d49bdc2b6d155067648f8fe1540c5de8f3cf8e157154"
],
"openbsd_riscv64": [
"go1.25.0.openbsd-riscv64.tar.gz",
"aa510ad25cf54c06cd9c70b6d80ded69cb20188ac6e1735655eef29ff7e7885f"
],
"plan9_386": [
"go1.25.0.plan9-386.tar.gz",
"46f8cef02086cf04bf186c5912776b56535178d4cb319cd19c9fdbdd29231986"
],
"plan9_amd64": [
"go1.25.0.plan9-amd64.tar.gz",
"29b34391d84095e44608a228f63f2f88113a37b74a79781353ec043dfbcb427b"
],
"plan9_arm": [
"go1.25.0.plan9-arm.tar.gz",
"0a047107d13ebe7943aaa6d54b1d7bbd2e45e68ce449b52915a818da715799c2"
],
"solaris_amd64": [
"go1.25.0.solaris-amd64.tar.gz",
"9977f9e4351984364a3b2b78f8b88bfd1d339812356d5237678514594b7d3611"
],
"windows_386": [
"go1.25.0.windows-386.zip",
"df9f39db82a803af0db639e3613a36681ab7a42866b1384b3f3a1045663961a7"
],
"windows_amd64": [
"go1.25.0.windows-amd64.zip",
"89efb4f9b30812eee083cc1770fdd2913c14d301064f6454851428f9707d190b"
],
"windows_arm64": [
"go1.25.0.windows-arm64.zip",
"27bab004c72b3d7bd05a69b6ec0fc54a309b4b78cc569dd963d8b3ec28bfdb8c"
]
}
}
}
}

44
README.md Normal file
View File

@@ -0,0 +1,44 @@
# rules_wails
Reusable Bazel rules for Wails applications.
Layout:
- `wails/`: core Wails rules and Go-backed action helpers.
- `wails_bun/`: optional Bun frontend integration for projects that stage frontend packages through Bazel.
- `examples/`: minimal usage examples for core Go and Bun-backed Wails apps.
Public entrypoints:
- `@rules_wails//wails:defs.bzl`
- `@rules_wails//wails_bun:defs.bzl`
## Bzlmod usage
```starlark
bazel_dep(name = "rules_wails", version = "0.1.0")
```
The Bun integration expects the standard `rules_bun` repositories and toolchains to be available via this ruleset's module setup.
## Public API
Core rules:
- `wails_toolchain`
- `wails_build_assets`
- `wails_generate_bindings`
- `wails_run`
- `wails_app`
Bun integration:
- `wails_bun_frontend_dist`
- `wails_bun_frontend_dev`
- `wails_bun_dev_session`
- `wails_bun_app`
See:
- [core README](wails/README.md)
- [Bun README](wails_bun/README.md)

1
bazel-bin Symbolic link
View File

@@ -0,0 +1 @@
/Users/eric/Library/Caches/bazel/_bazel_eric/cc2f40429f1d5fbfb8b6a40c23bb6094/execroot/_main/bazel-out/darwin_arm64-fastbuild/bin

1
bazel-out Symbolic link
View File

@@ -0,0 +1 @@
/Users/eric/Library/Caches/bazel/_bazel_eric/cc2f40429f1d5fbfb8b6a40c23bb6094/execroot/_main/bazel-out

1
bazel-testlogs Symbolic link
View File

@@ -0,0 +1 @@
/Users/eric/Library/Caches/bazel/_bazel_eric/cc2f40429f1d5fbfb8b6a40c23bb6094/execroot/_main/bazel-out/darwin_arm64-fastbuild/testlogs

1
bazel-wails_tools Symbolic link
View File

@@ -0,0 +1 @@
/Users/eric/Library/Caches/bazel/_bazel_eric/cc2f40429f1d5fbfb8b6a40c23bb6094/execroot/_main

View File

@@ -0,0 +1 @@
exports_files(["README.md"])

View File

@@ -0,0 +1,50 @@
# basic_go
Minimal core-only shape:
```bzl
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load("@rules_wails//wails:defs.bzl", "wails_build_assets", "wails_generate_bindings", "wails_run", "wails_toolchain")
go_binary(
name = "wails3",
srcs = ["scripts/wails3.go"],
)
wails_toolchain(
name = "example_wails_toolchain_impl",
go = "@my_go_sdk//:bin/go",
wails = ":wails3",
)
toolchain(
name = "example_wails_toolchain",
toolchain = ":example_wails_toolchain_impl",
toolchain_type = "@rules_wails//wails:toolchain_type",
)
go_binary(
name = "app",
srcs = ["main.go"],
)
wails_build_assets(
name = "build_assets",
srcs = ["build/config.yml"],
app_name = "example",
binary_name = "example",
strip_prefix = "build/",
)
wails_generate_bindings(
name = "bindings",
out_dir = "frontend/src/lib/bindings",
package_dir = ".",
)
wails_run(
name = "run",
binary = ":app",
build_assets = ":build_assets",
)
```

View File

@@ -0,0 +1 @@
exports_files(["README.md"])

View File

@@ -0,0 +1,25 @@
# bun_vite
Minimal Bun-layer shape:
```bzl
load("@rules_wails//wails_bun:defs.bzl", "wails_bun_app")
wails_bun_app(
name = "desktop",
app_binary = ":desktop_bin",
frontend_srcs = [
":frontend_sources",
"//pkgs/ui-kit:ui_kit_sources",
],
package_json = "frontend/package.json",
node_modules = "@deps//:node_modules",
build_asset_srcs = ["build/config.yml"],
app_name = "desktop",
binary_name = "desktop",
frontend_strip_prefix = "frontend/",
build_strip_prefix = "build/",
)
```
For Bun staging, each workspace package source target should include `package.json`.

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module github.com/Eriyc/rules_wails
go 1.26

12
wails/BUILD.bazel Normal file
View File

@@ -0,0 +1,12 @@
load(":private/toolchain.bzl", "wails_toolchain")
toolchain_type(
name = "toolchain_type",
visibility = ["//visibility:public"],
)
exports_files([
"defs.bzl",
"README.md",
])

28
wails/README.md Normal file
View File

@@ -0,0 +1,28 @@
# rules_wails core
Core Bazel rules for Wails applications.
Public API:
- `wails_toolchain`
- `wails_build_assets`
- `wails_generate_bindings`
- `wails_run`
- `wails_app`
The caller provides a registered toolchain with:
- `wails`: an executable target used to invoke Wails.
- `go`: an executable file used by that Wails wrapper for hermetic `go run` execution.
Notes:
- Core action helpers are Go binaries.
- `wails_run` launches the built application but does not build the Go binary for you.
- `wails_generate_bindings` stages the Bazel package tree so bindings generation runs from the correct module root.
Load with:
```starlark
load("@rules_wails//wails:defs.bzl", "wails_build_assets", "wails_generate_bindings", "wails_run", "wails_toolchain")
```

17
wails/defs.bzl Normal file
View File

@@ -0,0 +1,17 @@
"""Public API surface for core Wails rules."""
load(":private/build_assets.bzl", _wails_build_assets = "wails_build_assets")
load(":private/generate_bindings.bzl", _wails_generate_bindings = "wails_generate_bindings")
load(":private/macros.bzl", _wails_app = "wails_app")
load(":private/run.bzl", _wails_run = "wails_run")
load(":private/toolchain.bzl", _WailsToolchainInfo = "WailsToolchainInfo", _wails_toolchain = "wails_toolchain")
visibility("public")
WailsToolchainInfo = _WailsToolchainInfo
wails_toolchain = _wails_toolchain
wails_build_assets = _wails_build_assets
wails_generate_bindings = _wails_generate_bindings
wails_run = _wails_run
wails_app = _wails_app

View File

@@ -0,0 +1,58 @@
"""Rule for generating Wails build assets."""
load(":private/common.bzl", "write_manifest")
def _wails_build_assets_impl(ctx):
toolchain = ctx.toolchains["//wails:toolchain_type"].wails
out_dir = ctx.actions.declare_directory(ctx.label.name)
manifest = write_manifest(ctx, ctx.label.name + ".manifest", ctx.files.srcs, ctx.attr.strip_prefix)
args = ctx.actions.args()
args.add("--app-name", ctx.attr.app_name)
args.add("--binary-name", ctx.attr.binary_name)
args.add("--config-file", ctx.attr.config_file)
args.add("--manifest", manifest.path)
args.add("--out", out_dir.path)
args.add("--wails", toolchain.executable.path)
if ctx.attr.macos_minimum_system_version:
args.add("--macos-minimum-system-version", ctx.attr.macos_minimum_system_version)
ctx.actions.run(
executable = ctx.executable._tool,
arguments = [args],
inputs = depset(ctx.files.srcs + [manifest, toolchain.go_executable]),
outputs = [out_dir],
tools = [
ctx.executable._tool,
toolchain.files_to_run,
],
env = {
"GO_BIN": toolchain.go_executable.path,
},
mnemonic = "WailsBuildAssets",
progress_message = "Generating Wails build assets for %s" % ctx.label,
)
return [DefaultInfo(files = depset([out_dir]))]
wails_build_assets = rule(
implementation = _wails_build_assets_impl,
doc = "Runs `wails update build-assets` in a staged build directory.",
attrs = {
"app_name": attr.string(mandatory = True),
"binary_name": attr.string(mandatory = True),
"config_file": attr.string(default = "config.yml"),
"macos_minimum_system_version": attr.string(default = ""),
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
),
"strip_prefix": attr.string(default = ""),
"_tool": attr.label(
default = "//wails/tools:build_assets_action",
cfg = "exec",
executable = True,
),
},
toolchains = ["//wails:toolchain_type"],
)

58
wails/private/common.bzl Normal file
View File

@@ -0,0 +1,58 @@
"""Shared helpers for Wails rules."""
def _normalize_prefix(prefix):
if not prefix or prefix == ".":
return ""
normalized = prefix.strip("/")
if not normalized:
return ""
return normalized + "/"
def _manifest_rel_path(short_path, strip_prefix):
normalized_prefix = _normalize_prefix(strip_prefix)
rel_path = short_path
if normalized_prefix and rel_path.startswith(normalized_prefix):
rel_path = rel_path[len(normalized_prefix):]
return rel_path
def write_manifest(ctx, name, files, strip_prefix = ""):
manifest = ctx.actions.declare_file(name)
lines = []
for src in files:
lines.append("%s\t%s" % (src.path, _manifest_rel_path(src.short_path, strip_prefix)))
ctx.actions.write(
output = manifest,
content = "\n".join(lines) + "\n",
)
return manifest
def bash_launcher(resolve_lines, command_lines):
return """#!/usr/bin/env bash
set -euo pipefail
runfiles_dir="${{RUNFILES_DIR:-$0.runfiles}}"
export RUNFILES_DIR="${{runfiles_dir}}"
export RUNFILES="${{runfiles_dir}}"
resolve_runfile() {{
local short_path="$1"
if [[ "$short_path" == ../* ]]; then
echo "${{runfiles_dir}}/${{short_path#../}}"
else
echo "${{runfiles_dir}}/_main/${{short_path}}"
fi
}}
{resolve_lines}
{command_lines}
""".format(
resolve_lines = resolve_lines.strip(),
command_lines = command_lines.strip(),
)

View File

@@ -0,0 +1,205 @@
"""Rules for Wails binding generation."""
load(":private/common.bzl", "bash_launcher", "write_manifest")
def _normalize_relative_path(path):
if not path or path == ".":
return ""
return path.strip("/")
def _join_relative_path(base, child):
normalized_base = _normalize_relative_path(base)
normalized_child = _normalize_relative_path(child)
if normalized_base and normalized_child:
return normalized_base + "/" + normalized_child
if normalized_base:
return normalized_base
return normalized_child
def _package_glob_patterns(package_dir, out_dir):
normalized = package_dir.strip("./")
generated_dir = _join_relative_path(normalized, out_dir)
exclude_patterns = ["**/node_modules/**", "**/dist/**"]
if generated_dir:
exclude_patterns.append(generated_dir + "/**")
if not normalized:
return ("**", exclude_patterns)
return (
normalized + "/**",
exclude_patterns + [
normalized + "/node_modules/**",
normalized + "/dist/**",
],
)
def _workspace_package_dir(label_package, package_dir):
if label_package and package_dir and package_dir != ".":
return label_package + "/" + package_dir
if label_package:
return label_package
return package_dir
def _wails_generate_bindings_impl(ctx):
toolchain = ctx.toolchains["//wails:toolchain_type"].wails
out_tree = ctx.actions.declare_directory(ctx.label.name + "_out")
workspace_package_dir = _workspace_package_dir(ctx.label.package, ctx.attr.package_dir or ".")
manifest = write_manifest(
ctx,
ctx.label.name + ".manifest",
ctx.files.srcs,
workspace_package_dir,
)
build_args = ctx.actions.args()
build_args.add("--clean=%s" % ("true" if ctx.attr.clean else "false"))
build_args.add("--manifest", manifest.path)
build_args.add("--mode", "action")
build_args.add("--out", out_tree.path)
build_args.add("--out-dir", ctx.attr.out_dir)
build_args.add("--ts=%s" % ("true" if ctx.attr.ts else "false"))
build_args.add("--wails", toolchain.executable.path)
for extra_arg in ctx.attr.extra_args:
build_args.add("--extra-arg", extra_arg)
ctx.actions.run(
executable = ctx.executable._tool,
arguments = [build_args],
inputs = depset(ctx.files.srcs + [manifest, toolchain.go_executable]),
outputs = [out_tree],
tools = [
ctx.executable._tool,
toolchain.files_to_run,
],
env = {
"GO_BIN": toolchain.go_executable.path,
},
mnemonic = "WailsGenerateBindings",
progress_message = "Generating Wails bindings for %s" % ctx.label,
)
launcher = ctx.actions.declare_file(ctx.label.name)
resolve_lines = """
tool="$(resolve_runfile "{tool_short_path}")"
wails="$(resolve_runfile "{wails_short_path}")"
go_bin="$(resolve_runfile "{go_short_path}")"
workspace_root="${{BUILD_WORKSPACE_DIRECTORY:-}}"
if [[ -z "$workspace_root" ]]; then
echo "BUILD_WORKSPACE_DIRECTORY is required for bazel run bindings generation" >&2
exit 1
fi
workspace_package_dir="{workspace_package_dir}"
if [[ -n "$workspace_package_dir" && "$workspace_package_dir" != "." ]]; then
workspace_package_dir="${{workspace_root}}/${{workspace_package_dir}}"
else
workspace_package_dir="${{workspace_root}}"
fi
""".format(
tool_short_path = ctx.executable._tool.short_path,
wails_short_path = toolchain.executable.short_path,
go_short_path = toolchain.go_executable.short_path,
workspace_package_dir = workspace_package_dir or ".",
)
extra_args_lines = "\n".join([
'cmd+=(--extra-arg %s)' % _shell_quote(arg)
for arg in ctx.attr.extra_args
])
command_lines = """
cmd=(
"$tool"
--clean={clean}
--mode workspace
--out-dir {out_dir}
--package-dir "$workspace_package_dir"
--ts={ts}
--wails "$wails"
)
{extra_args_lines}
export GO_BIN="$go_bin"
exec "${{cmd[@]}}"
""".format(
clean = "true" if ctx.attr.clean else "false",
out_dir = _shell_quote(ctx.attr.out_dir),
ts = "true" if ctx.attr.ts else "false",
extra_args_lines = extra_args_lines,
)
ctx.actions.write(
output = launcher,
is_executable = True,
content = bash_launcher(resolve_lines, command_lines),
)
runfiles = ctx.runfiles(
files = [
ctx.executable._tool,
toolchain.executable,
toolchain.go_executable,
],
transitive_files = depset(transitive = [
ctx.attr._tool[DefaultInfo].default_runfiles.files,
toolchain.default_runfiles.files,
toolchain.go_default_runfiles.files,
]),
)
return [
DefaultInfo(
executable = launcher,
files = depset([out_tree]),
runfiles = runfiles,
),
]
def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'"
_wails_generate_bindings_rule = rule(
implementation = _wails_generate_bindings_impl,
attrs = {
"clean": attr.bool(default = True),
"extra_args": attr.string_list(),
"out_dir": attr.string(mandatory = True),
"package_dir": attr.string(default = "."),
"srcs": attr.label_list(
allow_files = True,
mandatory = True,
),
"ts": attr.bool(default = True),
"_tool": attr.label(
default = "//wails/tools:generate_bindings_action",
cfg = "exec",
executable = True,
),
},
executable = True,
toolchains = ["//wails:toolchain_type"],
)
def wails_generate_bindings(
name,
out_dir,
package_dir = ".",
clean = True,
ts = True,
extra_args = None,
tags = None,
visibility = None):
include_pattern, exclude_patterns = _package_glob_patterns(package_dir, out_dir)
_wails_generate_bindings_rule(
name = name,
clean = clean,
extra_args = extra_args or [],
out_dir = out_dir,
package_dir = package_dir,
srcs = native.glob([include_pattern], exclude = exclude_patterns),
tags = tags,
visibility = visibility,
ts = ts,
)

27
wails/private/macros.bzl Normal file
View File

@@ -0,0 +1,27 @@
"""Convenience macros for Wails rules."""
load(":private/generate_bindings.bzl", "wails_generate_bindings")
load(":private/run.bzl", "wails_run")
def wails_app(name, binary, build_assets, bindings = None, icon = None, visibility = None, tags = None):
wails_run(
name = name + "_run",
binary = binary,
build_assets = build_assets,
icon = icon,
tags = tags,
visibility = visibility,
)
if bindings:
wails_generate_bindings(
name = name + "_bindings",
out_dir = bindings["out_dir"],
package_dir = bindings.get("package_dir", "."),
clean = bindings.get("clean", True),
ts = bindings.get("ts", True),
extra_args = bindings.get("extra_args", []),
tags = tags,
visibility = visibility,
)

87
wails/private/run.bzl Normal file
View File

@@ -0,0 +1,87 @@
"""Runnable Wails app launcher rule."""
load(":private/common.bzl", "bash_launcher")
def _wails_run_impl(ctx):
launcher = ctx.actions.declare_file(ctx.label.name)
resolve_lines = """
tool="$(resolve_runfile "{tool_short_path}")"
binary="$(resolve_runfile "{binary_short_path}")"
build_assets="$(resolve_runfile "{build_assets_short_path}")"
icon=""
if [[ -n "{icon_short_path}" ]]; then
icon="$(resolve_runfile "{icon_short_path}")"
fi
""".format(
tool_short_path = ctx.executable._tool.short_path,
binary_short_path = ctx.executable.binary.short_path,
build_assets_short_path = ctx.files.build_assets[0].short_path,
icon_short_path = ctx.file.icon.short_path if ctx.file.icon else "",
)
command_lines = """
exec "$tool" \
--binary "$binary" \
--build-assets "$build_assets" \
--frontend-url {frontend_url} \
--icon "$icon" \
--mode {mode}
""".format(
frontend_url = _shell_quote(ctx.attr.frontend_url),
mode = _shell_quote(ctx.attr.mode),
)
ctx.actions.write(
output = launcher,
is_executable = True,
content = bash_launcher(resolve_lines, command_lines),
)
transitive_files = [
ctx.attr._tool[DefaultInfo].default_runfiles.files,
ctx.attr.binary[DefaultInfo].default_runfiles.files,
]
runfiles = ctx.runfiles(
files = [
ctx.executable._tool,
ctx.executable.binary,
] + ctx.files.build_assets + ([ctx.file.icon] if ctx.file.icon else []),
transitive_files = depset(transitive = transitive_files),
)
return [DefaultInfo(executable = launcher, runfiles = runfiles)]
def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'"
wails_run = rule(
implementation = _wails_run_impl,
doc = "Creates a runnable target that launches a Wails application.",
attrs = {
"binary": attr.label(
mandatory = True,
executable = True,
cfg = "target",
),
"build_assets": attr.label(
mandatory = True,
allow_files = True,
),
"frontend_url": attr.string(default = "http://127.0.0.1:9245"),
"icon": attr.label(
allow_single_file = True,
),
"mode": attr.string(
default = "run",
values = ["dev", "run"],
),
"_tool": attr.label(
default = "//wails/tools:launch_app",
cfg = "exec",
executable = True,
),
},
executable = True,
)

View File

@@ -0,0 +1,48 @@
"""Toolchain definitions for Wails."""
WailsToolchainInfo = provider(
doc = "Caller-supplied Wails executable, Go executable, and runfiles.",
fields = {
"default_runfiles": "Runfiles for the Wails executable.",
"go_default_runfiles": "Runfiles for the Go executable.",
"go_executable": "Executable file for the Go tool.",
"executable": "Executable file for the Wails tool.",
"files_to_run": "FilesToRunProvider for the Wails tool.",
},
)
def _wails_toolchain_impl(ctx):
wails_default_info = ctx.attr.wails[DefaultInfo]
go_default_info = ctx.attr.go[DefaultInfo]
return [
platform_common.ToolchainInfo(
wails = WailsToolchainInfo(
default_runfiles = wails_default_info.default_runfiles,
go_default_runfiles = go_default_info.default_runfiles,
go_executable = ctx.file.go,
executable = ctx.executable.wails,
files_to_run = wails_default_info.files_to_run,
),
),
]
wails_toolchain = rule(
implementation = _wails_toolchain_impl,
attrs = {
"go": attr.label(
mandatory = True,
cfg = "exec",
allow_single_file = True,
doc = "Executable file used for hermetic `go run` invocations inside the Wails tool.",
),
"wails": attr.label(
mandatory = True,
cfg = "exec",
executable = True,
allow_files = True,
doc = "Executable target used to invoke Wails.",
),
},
doc = "Registers caller-supplied Wails and Go executables as a Bazel toolchain.",
)

25
wails/tools/BUILD.bazel Normal file
View File

@@ -0,0 +1,25 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
go_binary(
name = "build_assets_action",
srcs = ["build_assets_action.go"],
importpath = "github.com/Eriyc/rules_wails/wails/tools/build_assets_action",
pure = "off",
visibility = ["//visibility:public"],
)
go_binary(
name = "generate_bindings_action",
srcs = ["generate_bindings_action.go"],
importpath = "github.com/Eriyc/rules_wails/wails/tools/generate_bindings_action",
pure = "off",
visibility = ["//visibility:public"],
)
go_binary(
name = "launch_app",
srcs = ["launch_app.go"],
importpath = "github.com/Eriyc/rules_wails/wails/tools/launch_app",
pure = "off",
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,225 @@
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
func main() {
var appName string
var binaryName string
var configFile string
var macOSMinimumSystemVersion string
var manifestPath string
var outDir string
var wailsPath string
flag.StringVar(&appName, "app-name", "", "")
flag.StringVar(&binaryName, "binary-name", "", "")
flag.StringVar(&configFile, "config-file", "config.yml", "")
flag.StringVar(&macOSMinimumSystemVersion, "macos-minimum-system-version", "", "")
flag.StringVar(&manifestPath, "manifest", "", "")
flag.StringVar(&outDir, "out", "", "")
flag.StringVar(&wailsPath, "wails", "", "")
flag.Parse()
require(manifestPath != "", "missing --manifest")
require(outDir != "", "missing --out")
require(wailsPath != "", "missing --wails")
require(appName != "", "missing --app-name")
require(binaryName != "", "missing --binary-name")
var err error
wailsPath, err = filepath.Abs(wailsPath)
must(err)
must(resolveGoEnvToAbsolutePath())
tempRoot, err := os.MkdirTemp("", "rules-wails-build-assets-*")
must(err)
defer func() {
_ = os.Chmod(tempRoot, 0o755)
_ = os.RemoveAll(tempRoot)
}()
workDir := filepath.Join(tempRoot, "work")
homeDir := filepath.Join(tempRoot, "home")
must(os.MkdirAll(workDir, 0o755))
must(os.MkdirAll(homeDir, 0o755))
must(stageManifest(manifestPath, workDir))
command := exec.Command(
wailsPath,
"update",
"build-assets",
"-name", appName,
"-binaryname", binaryName,
"-config", filepath.Join(workDir, configFile),
"-dir", workDir,
)
command.Dir = workDir
command.Env = append(os.Environ(),
"HOME="+homeDir,
"LC_ALL=C",
"TZ=UTC",
)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
must(command.Run())
updateMacOSMinimumVersion(filepath.Join(workDir, "darwin", "Info.plist"), macOSMinimumSystemVersion)
updateMacOSMinimumVersion(filepath.Join(workDir, "darwin", "Info.dev.plist"), macOSMinimumSystemVersion)
must(os.RemoveAll(outDir))
must(os.MkdirAll(outDir, 0o755))
must(copyTree(workDir, outDir))
}
func resolveGoEnvToAbsolutePath() error {
goBinary := os.Getenv("GO_BIN")
if goBinary == "" || filepath.IsAbs(goBinary) {
return nil
}
absolutePath, err := filepath.Abs(goBinary)
if err != nil {
return err
}
return os.Setenv("GO_BIN", absolutePath)
}
func updateMacOSMinimumVersion(path string, minimumVersion string) {
if minimumVersion == "" {
return
}
if _, err := os.Stat(path); err != nil {
return
}
if _, err := os.Stat("/usr/libexec/PlistBuddy"); err != nil {
return
}
setCommand := exec.Command("/usr/libexec/PlistBuddy", "-c", "Set :LSMinimumSystemVersion "+minimumVersion, path)
if err := setCommand.Run(); err == nil {
return
}
addCommand := exec.Command("/usr/libexec/PlistBuddy", "-c", "Add :LSMinimumSystemVersion string "+minimumVersion, path)
_ = addCommand.Run()
}
func stageManifest(manifestPath string, destinationRoot string) error {
entries, err := readManifest(manifestPath)
if err != nil {
return err
}
for _, entry := range entries {
destinationPath := filepath.Join(destinationRoot, entry.relativePath)
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
return err
}
if err := copyFile(entry.sourcePath, destinationPath); err != nil {
return err
}
}
return nil
}
func readManifest(path string) ([]manifestEntry, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
entries := make([]manifestEntry, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
parts := strings.SplitN(line, "\t", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid manifest line: %s", line)
}
entries = append(entries, manifestEntry{
sourcePath: parts[0],
relativePath: parts[1],
})
}
return entries, scanner.Err()
}
func copyTree(sourceRoot string, destinationRoot string) error {
return filepath.Walk(sourceRoot, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
relativePath, err := filepath.Rel(sourceRoot, path)
if err != nil {
return err
}
if relativePath == "." {
return nil
}
destinationPath := filepath.Join(destinationRoot, relativePath)
if info.IsDir() {
return os.MkdirAll(destinationPath, 0o755)
}
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
return err
}
return copyFile(path, destinationPath)
})
}
func copyFile(sourcePath string, destinationPath string) error {
sourceFile, err := os.Open(sourcePath)
if err != nil {
return err
}
defer sourceFile.Close()
destinationFile, err := os.Create(destinationPath)
if err != nil {
return err
}
defer destinationFile.Close()
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
return err
}
return destinationFile.Chmod(0o644)
}
func must(err error) {
if err != nil {
panic(err)
}
}
func require(condition bool, message string) {
if !condition {
panic(message)
}
}
type manifestEntry struct {
sourcePath string
relativePath string
}

View File

@@ -0,0 +1,239 @@
package main
import (
"bufio"
"flag"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"strings"
)
type repeatedFlag []string
func (value *repeatedFlag) String() string {
return strings.Join(*value, ",")
}
func (value *repeatedFlag) Set(input string) error {
*value = append(*value, input)
return nil
}
func main() {
var clean bool
var extraArgs repeatedFlag
var manifestPath string
var mode string
var outDir string
var outputPath string
var packageDir string
var ts bool
var wailsPath string
flag.BoolVar(&clean, "clean", true, "")
flag.Var(&extraArgs, "extra-arg", "")
flag.StringVar(&manifestPath, "manifest", "", "")
flag.StringVar(&mode, "mode", "", "")
flag.StringVar(&outDir, "out-dir", "", "")
flag.StringVar(&outputPath, "out", "", "")
flag.StringVar(&packageDir, "package-dir", "", "")
flag.BoolVar(&ts, "ts", true, "")
flag.StringVar(&wailsPath, "wails", "", "")
flag.Parse()
require(mode != "", "missing --mode")
require(outDir != "", "missing --out-dir")
require(wailsPath != "", "missing --wails")
var err error
wailsPath, err = filepath.Abs(wailsPath)
must(err)
must(resolveGoEnvToAbsolutePath())
switch mode {
case "action":
require(manifestPath != "", "missing --manifest")
require(outputPath != "", "missing --out")
must(runActionMode(manifestPath, outputPath, outDir, wailsPath, clean, ts, extraArgs))
case "workspace":
require(packageDir != "", "missing --package-dir")
must(runWorkspaceMode(packageDir, outDir, wailsPath, clean, ts, extraArgs))
default:
panic("unsupported --mode")
}
}
func resolveGoEnvToAbsolutePath() error {
goBinary := os.Getenv("GO_BIN")
if goBinary == "" || filepath.IsAbs(goBinary) {
return nil
}
absolutePath, err := filepath.Abs(goBinary)
if err != nil {
return err
}
return os.Setenv("GO_BIN", absolutePath)
}
func runActionMode(manifestPath string, outputPath string, outDir string, wailsPath string, clean bool, ts bool, extraArgs []string) error {
tempRoot, err := os.MkdirTemp("", "rules-wails-bindings-*")
if err != nil {
return err
}
defer os.RemoveAll(tempRoot)
workDir := filepath.Join(tempRoot, "work")
if err := os.MkdirAll(workDir, 0o755); err != nil {
return err
}
if err := stageManifest(manifestPath, workDir); err != nil {
return err
}
if err := runBindings(workDir, outDir, wailsPath, clean, ts, extraArgs); err != nil {
return err
}
if err := os.RemoveAll(outputPath); err != nil {
return err
}
if err := os.MkdirAll(outputPath, 0o755); err != nil {
return err
}
return copyTree(filepath.Join(workDir, outDir), outputPath)
}
func runWorkspaceMode(packageDir string, outDir string, wailsPath string, clean bool, ts bool, extraArgs []string) error {
return runBindings(packageDir, outDir, wailsPath, clean, ts, extraArgs)
}
func runBindings(cwd string, outDir string, wailsPath string, clean bool, ts bool, extraArgs []string) error {
commandArgs := []string{"generate", "bindings", "-d", outDir}
if clean {
commandArgs = append(commandArgs, "-clean")
}
if ts {
commandArgs = append(commandArgs, "-ts")
}
commandArgs = append(commandArgs, extraArgs...)
command := exec.Command(wailsPath, commandArgs...)
command.Dir = cwd
command.Stdout = os.Stdout
command.Stderr = os.Stderr
return command.Run()
}
func stageManifest(manifestPath string, destinationRoot string) error {
entries, err := readManifest(manifestPath)
if err != nil {
return err
}
for _, entry := range entries {
destinationPath := filepath.Join(destinationRoot, entry.relativePath)
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
return err
}
if err := copyFile(entry.sourcePath, destinationPath); err != nil {
return err
}
}
return nil
}
func readManifest(path string) ([]manifestEntry, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
entries := make([]manifestEntry, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
parts := strings.SplitN(line, "\t", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid manifest line: %s", line)
}
entries = append(entries, manifestEntry{
sourcePath: parts[0],
relativePath: parts[1],
})
}
return entries, scanner.Err()
}
func copyTree(sourceRoot string, destinationRoot string) error {
return filepath.Walk(sourceRoot, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
relativePath, err := filepath.Rel(sourceRoot, path)
if err != nil {
return err
}
if relativePath == "." {
return nil
}
destinationPath := filepath.Join(destinationRoot, relativePath)
if info.IsDir() {
return os.MkdirAll(destinationPath, 0o755)
}
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
return err
}
return copyFile(path, destinationPath)
})
}
func copyFile(sourcePath string, destinationPath string) error {
sourceFile, err := os.Open(sourcePath)
if err != nil {
return err
}
defer sourceFile.Close()
destinationFile, err := os.Create(destinationPath)
if err != nil {
return err
}
defer destinationFile.Close()
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
return err
}
return destinationFile.Chmod(0o644)
}
func must(err error) {
if err != nil {
panic(err)
}
}
func require(condition bool, message string) {
if !condition {
panic(message)
}
}
type manifestEntry struct {
sourcePath string
relativePath string
}

139
wails/tools/launch_app.go Normal file
View File

@@ -0,0 +1,139 @@
package main
import (
"flag"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
func main() {
var binaryPath string
var buildAssetsPath string
var frontendURL string
var iconPath string
var mode string
flag.StringVar(&binaryPath, "binary", "", "")
flag.StringVar(&buildAssetsPath, "build-assets", "", "")
flag.StringVar(&frontendURL, "frontend-url", "http://127.0.0.1:9245", "")
flag.StringVar(&iconPath, "icon", "", "")
flag.StringVar(&mode, "mode", "run", "")
flag.Parse()
require(binaryPath != "", "missing --binary")
require(buildAssetsPath != "", "missing --build-assets")
environment := os.Environ()
if mode == "dev" && os.Getenv("FRONTEND_DEVSERVER_URL") == "" {
environment = append(environment, "FRONTEND_DEVSERVER_URL="+frontendURL)
}
if runtime.GOOS == "darwin" {
os.Exit(runDarwin(binaryPath, buildAssetsPath, iconPath, mode, environment))
}
command := exec.Command(binaryPath)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
command.Stdin = os.Stdin
command.Env = environment
if err := command.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
os.Exit(exitError.ExitCode())
}
panic(err)
}
}
func runDarwin(binaryPath string, buildAssetsPath string, iconPath string, mode string, environment []string) int {
appName := strings.TrimSuffix(filepath.Base(binaryPath), filepath.Ext(binaryPath))
if appName == "" {
appName = "wails-app"
}
appDir := filepath.Join(os.TempDir(), appName+"-bazel-"+mode)
defer os.RemoveAll(appDir)
appContents := filepath.Join(appDir, "Contents")
appMacOS := filepath.Join(appContents, "MacOS")
appResources := filepath.Join(appContents, "Resources")
appBinary := filepath.Join(appMacOS, appName)
must(os.MkdirAll(appMacOS, 0o755))
must(os.MkdirAll(appResources, 0o755))
must(copyFile(binaryPath, appBinary, 0o755))
for _, candidate := range []string{
filepath.Join(buildAssetsPath, "darwin", "Info.dev.plist"),
filepath.Join(buildAssetsPath, "darwin", "Info.plist"),
} {
if mode != "dev" && strings.HasSuffix(candidate, "Info.dev.plist") {
continue
}
if _, err := os.Stat(candidate); err == nil {
must(copyFile(candidate, filepath.Join(appContents, "Info.plist"), 0o644))
break
}
}
if iconPath != "" {
if _, err := os.Stat(iconPath); err == nil {
must(copyFile(iconPath, filepath.Join(appResources, filepath.Base(iconPath)), 0o644))
}
}
if _, err := os.Stat("/usr/bin/codesign"); err == nil {
codesign := exec.Command("/usr/bin/codesign", "--force", "--deep", "--sign", "-", appDir)
_ = codesign.Run()
}
command := exec.Command(appBinary)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
command.Stdin = os.Stdin
command.Env = environment
if err := command.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
return exitError.ExitCode()
}
panic(err)
}
return 0
}
func copyFile(sourcePath string, destinationPath string, mode os.FileMode) error {
sourceFile, err := os.Open(sourcePath)
if err != nil {
return err
}
defer sourceFile.Close()
destinationFile, err := os.Create(destinationPath)
if err != nil {
return err
}
defer destinationFile.Close()
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
return err
}
return destinationFile.Chmod(mode)
}
func must(err error) {
if err != nil {
panic(err)
}
}
func require(condition bool, message string) {
if !condition {
panic(message)
}
}

5
wails_bun/BUILD.bazel Normal file
View File

@@ -0,0 +1,5 @@
exports_files([
"defs.bzl",
"README.md",
])

23
wails_bun/README.md Normal file
View File

@@ -0,0 +1,23 @@
# rules_wails Bun integration
Optional `rules_bun` integration for Wails projects that build their frontend
with Bun and Vite-style package scripts.
Public API:
- `wails_bun_frontend_dist`
- `wails_bun_frontend_dev`
- `wails_bun_dev_session`
- `wails_bun_app`
Important contract:
- `ts_library` is not enough for frontend package staging.
- Package-source targets passed to `wails_bun_frontend_dist` should include both the package sources and `package.json`.
- Consumers should provide package-source targets that include both application sources and `package.json`.
Load with:
```starlark
load("@rules_wails//wails_bun:defs.bzl", "wails_bun_dev_session", "wails_bun_frontend_dev", "wails_bun_frontend_dist")
```

13
wails_bun/defs.bzl Normal file
View File

@@ -0,0 +1,13 @@
"""Public API for Bun-backed Wails helpers."""
load(":private/dev_session.bzl", _wails_bun_dev_session = "wails_bun_dev_session")
load(":private/frontend_dist.bzl", _wails_bun_frontend_dev = "wails_bun_frontend_dev", _wails_bun_frontend_dist = "wails_bun_frontend_dist")
load(":private/macros.bzl", _wails_bun_app = "wails_bun_app")
visibility("public")
wails_bun_frontend_dist = _wails_bun_frontend_dist
wails_bun_frontend_dev = _wails_bun_frontend_dev
wails_bun_dev_session = _wails_bun_dev_session
wails_bun_app = _wails_bun_app

View File

@@ -0,0 +1,198 @@
"""Dev-session rules for Bun-backed Wails apps."""
load("//wails:private/common.bzl", "bash_launcher")
def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'"
def _absolute_label(label_package, name):
if label_package:
return "//%s:%s" % (label_package, name)
return "//:%s" % name
def _wails_bun_watch_run_impl(ctx):
launcher = ctx.actions.declare_file(ctx.label.name)
resolve_lines = """
tool="$(resolve_runfile "{tool_short_path}")"
binary="$(resolve_runfile "{binary_short_path}")"
build_assets="$(resolve_runfile "{build_assets_short_path}")"
bindings=""
if [[ -n "{bindings_short_path}" ]]; then
bindings="$(resolve_runfile "{bindings_short_path}")"
fi
icon=""
if [[ -n "{icon_short_path}" ]]; then
icon="$(resolve_runfile "{icon_short_path}")"
fi
""".format(
tool_short_path = ctx.executable._tool.short_path,
binary_short_path = ctx.executable.binary.short_path,
build_assets_short_path = ctx.files.build_assets[0].short_path,
bindings_short_path = ctx.executable.bindings.short_path if ctx.executable.bindings else "",
icon_short_path = ctx.file.icon.short_path if ctx.file.icon else "",
)
binding_command = ""
if ctx.executable.bindings:
binding_command = "\"$bindings\"\n"
command_lines = """
{binding_command}exec "$tool" \
--binary "$binary" \
--build-assets "$build_assets" \
--frontend-url {frontend_url} \
--icon "$icon" \
--mode 'dev'
""".format(
binding_command = binding_command,
frontend_url = _shell_quote(ctx.attr.frontend_url),
)
ctx.actions.write(
output = launcher,
is_executable = True,
content = bash_launcher(resolve_lines, command_lines),
)
transitive_files = [
ctx.attr._tool[DefaultInfo].default_runfiles.files,
ctx.attr.binary[DefaultInfo].default_runfiles.files,
]
files = [
ctx.executable._tool,
ctx.executable.binary,
] + ctx.files.build_assets + ([ctx.file.icon] if ctx.file.icon else [])
if ctx.attr.bindings:
transitive_files.append(ctx.attr.bindings[DefaultInfo].default_runfiles.files)
files.append(ctx.executable.bindings)
runfiles = ctx.runfiles(
files = files,
transitive_files = depset(transitive = transitive_files),
)
return [DefaultInfo(executable = launcher, runfiles = runfiles)]
_wails_bun_watch_run = rule(
implementation = _wails_bun_watch_run_impl,
attrs = {
"binary": attr.label(
mandatory = True,
executable = True,
cfg = "target",
),
"bindings": attr.label(
executable = True,
cfg = "target",
),
"build_assets": attr.label(
mandatory = True,
allow_files = True,
),
"frontend_url": attr.string(default = "http://127.0.0.1:9245"),
"icon": attr.label(allow_single_file = True),
"_tool": attr.label(
default = "//wails/tools:launch_app",
cfg = "exec",
executable = True,
),
},
executable = True,
)
def _wails_bun_dev_session_impl(ctx):
launcher = ctx.actions.declare_file(ctx.label.name)
resolve_lines = """
tool="$(resolve_runfile "{tool_short_path}")"
frontend_dev="$(resolve_runfile "{frontend_dev_short_path}")"
""".format(
tool_short_path = ctx.executable._tool.short_path,
frontend_dev_short_path = ctx.executable.frontend_dev.short_path,
)
command_lines = """
exec "$tool" \
--frontend-dev "$frontend_dev" \
--frontend-url {frontend_url} \
--watch-target {watch_target} \
--workspace-dir {workspace_dir}
""".format(
frontend_url = _shell_quote(ctx.attr.frontend_url),
watch_target = _shell_quote(ctx.attr.watch_target),
workspace_dir = _shell_quote(ctx.attr.workspace_dir),
)
ctx.actions.write(
output = launcher,
is_executable = True,
content = bash_launcher(resolve_lines, command_lines),
)
runfiles = ctx.runfiles(
files = [
ctx.executable._tool,
ctx.executable.frontend_dev,
],
transitive_files = depset(transitive = [
ctx.attr._tool[DefaultInfo].default_runfiles.files,
ctx.attr.frontend_dev[DefaultInfo].default_runfiles.files,
]),
)
return [DefaultInfo(executable = launcher, runfiles = runfiles)]
_wails_bun_dev_session_rule = rule(
implementation = _wails_bun_dev_session_impl,
attrs = {
"frontend_dev": attr.label(
mandatory = True,
executable = True,
cfg = "target",
),
"frontend_url": attr.string(default = "http://127.0.0.1:9245"),
"watch_target": attr.string(mandatory = True),
"workspace_dir": attr.string(default = "."),
"_tool": attr.label(
default = "//wails_bun/tools:bun_dev_session",
cfg = "exec",
executable = True,
),
},
executable = True,
)
def wails_bun_dev_session(
name,
workspace_dir,
frontend_dev,
app_binary,
build_assets,
bindings_target = None,
icon = None,
frontend_url = "http://127.0.0.1:9245",
tags = None,
visibility = None):
watch_name = name + "_watch"
_wails_bun_watch_run(
name = watch_name,
binary = app_binary,
bindings = bindings_target,
build_assets = build_assets,
frontend_url = frontend_url,
icon = icon,
tags = ["manual"],
visibility = ["//visibility:private"],
)
_wails_bun_dev_session_rule(
name = name,
frontend_dev = frontend_dev,
frontend_url = frontend_url,
tags = tags,
visibility = visibility,
watch_target = _absolute_label(native.package_name(), watch_name),
workspace_dir = workspace_dir,
)

View File

@@ -0,0 +1,274 @@
"""Bun frontend build helpers for Wails."""
load("//wails:private/common.bzl", "bash_launcher", "write_manifest")
def _node_modules_root_from_path(path):
marker = "/node_modules/"
marker_index = path.find(marker)
if marker_index < 0:
return None
return path[:marker_index + len("/node_modules")]
def _dirname(path):
index = path.rfind("/")
if index < 0:
return "."
return path[:index] or "."
def _wails_bun_frontend_dist_impl(ctx):
out_dir = ctx.actions.declare_directory(ctx.label.name)
manifest_srcs = list(ctx.files.srcs)
if ctx.file.package_json.path not in [src.path for src in manifest_srcs]:
manifest_srcs.append(ctx.file.package_json)
manifest = write_manifest(
ctx,
ctx.label.name + ".manifest",
manifest_srcs,
ctx.attr.strip_prefix,
)
if not ctx.files.node_modules:
fail("wails_bun_frontend_dist requires a non-empty node_modules tree")
workspace_marker = ""
if ctx.attr.workspace_dir:
workspace_marker = "/%s/node_modules/" % ctx.attr.workspace_dir.strip("/")
shortest_path = None
shared_node_modules_root = None
workspace_node_modules_root = None
for src in ctx.files.node_modules:
if shortest_path == None or len(src.path) < len(shortest_path):
shortest_path = src.path
if workspace_marker and workspace_marker in src.path and workspace_node_modules_root == None:
workspace_node_modules_root = _node_modules_root_from_path(src.path)
if shortest_path:
shared_node_modules_root = _node_modules_root_from_path(shortest_path)
node_modules_root = workspace_node_modules_root or shared_node_modules_root
if node_modules_root == None or shared_node_modules_root == None:
fail("unable to determine node_modules roots from node_modules inputs")
package_json_rel = ctx.file.package_json.short_path
if ctx.attr.strip_prefix and package_json_rel.startswith(ctx.attr.strip_prefix):
package_json_rel = package_json_rel[len(ctx.attr.strip_prefix):]
package_dir = _dirname(package_json_rel)
args = ctx.actions.args()
args.add("--build-script", ctx.attr.build_script)
args.add("--manifest", manifest.path)
args.add("--node-modules-root", node_modules_root)
args.add("--out", out_dir.path)
args.add("--package-dir", package_dir)
args.add("--shared-node-modules-root", shared_node_modules_root)
args.add("--bun-darwin-aarch64", ctx.file._bun_darwin_aarch64.path)
args.add("--bun-darwin-x64", ctx.file._bun_darwin_x64.path)
args.add("--bun-linux-aarch64", ctx.file._bun_linux_aarch64.path)
args.add("--bun-linux-x64", ctx.file._bun_linux_x64.path)
args.add("--bun-windows-x64", ctx.file._bun_windows_x64.path)
if ctx.attr.workspace_dir:
args.add("--workspace-dir", ctx.attr.workspace_dir)
ctx.actions.run(
executable = ctx.executable._tool,
arguments = [args],
inputs = depset(
manifest_srcs +
ctx.files.node_modules + [
manifest,
ctx.file._bun_darwin_aarch64,
ctx.file._bun_darwin_x64,
ctx.file._bun_linux_aarch64,
ctx.file._bun_linux_x64,
ctx.file._bun_windows_x64,
],
),
outputs = [out_dir],
tools = [ctx.attr._tool[DefaultInfo].files_to_run],
mnemonic = "WailsBunFrontendDist",
progress_message = "Building Bun frontend dist for %s" % ctx.label,
)
return [DefaultInfo(files = depset([out_dir]))]
def _wails_bun_frontend_dev_impl(ctx):
launcher = ctx.actions.declare_file(ctx.label.name)
package_dir = _dirname(ctx.file.package_json.short_path)
resolve_lines = """
tool="$(resolve_runfile "{tool_short_path}")"
bun_darwin_aarch64="$(resolve_runfile "{bun_darwin_aarch64_short_path}")"
bun_darwin_x64="$(resolve_runfile "{bun_darwin_x64_short_path}")"
bun_linux_aarch64="$(resolve_runfile "{bun_linux_aarch64_short_path}")"
bun_linux_x64="$(resolve_runfile "{bun_linux_x64_short_path}")"
bun_windows_x64="$(resolve_runfile "{bun_windows_x64_short_path}")"
""".format(
tool_short_path = ctx.executable._tool.short_path,
bun_darwin_aarch64_short_path = ctx.file._bun_darwin_aarch64.short_path,
bun_darwin_x64_short_path = ctx.file._bun_darwin_x64.short_path,
bun_linux_aarch64_short_path = ctx.file._bun_linux_aarch64.short_path,
bun_linux_x64_short_path = ctx.file._bun_linux_x64.short_path,
bun_windows_x64_short_path = ctx.file._bun_windows_x64.short_path,
)
command_lines = """
exec "$tool" \
--bun-darwin-aarch64 "$bun_darwin_aarch64" \
--bun-darwin-x64 "$bun_darwin_x64" \
--bun-linux-aarch64 "$bun_linux_aarch64" \
--bun-linux-x64 "$bun_linux_x64" \
--bun-windows-x64 "$bun_windows_x64" \
--package-dir {package_dir} \
--script {script}
""".format(
package_dir = _shell_quote(ctx.attr.workspace_dir or package_dir),
script = _shell_quote(ctx.attr.script),
)
ctx.actions.write(
output = launcher,
is_executable = True,
content = bash_launcher(resolve_lines, command_lines),
)
runfiles = ctx.runfiles(
files = [
ctx.executable._tool,
ctx.file._bun_darwin_aarch64,
ctx.file._bun_darwin_x64,
ctx.file._bun_linux_aarch64,
ctx.file._bun_linux_x64,
ctx.file._bun_windows_x64,
] + ([ctx.file.package_json] if ctx.file.package_json else []),
transitive_files = depset(transitive = [
ctx.attr._tool[DefaultInfo].default_runfiles.files,
]),
)
return [DefaultInfo(executable = launcher, runfiles = runfiles)]
def _shell_quote(value):
return "'" + value.replace("'", "'\"'\"'") + "'"
wails_bun_frontend_dist = rule(
implementation = _wails_bun_frontend_dist_impl,
attrs = {
"build_script": attr.string(default = "build"),
"node_modules": attr.label(
mandatory = True,
allow_files = True,
),
"package_json": attr.label(
mandatory = True,
allow_single_file = True,
),
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
),
"strip_prefix": attr.string(default = ""),
"workspace_dir": attr.string(default = ""),
"_tool": attr.label(
default = "//wails_bun/tools:frontend_dist_action",
cfg = "exec",
executable = True,
),
"_bun_darwin_aarch64": attr.label(
default = "@bun_darwin_aarch64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_darwin_x64": attr.label(
default = "@bun_darwin_x64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_linux_aarch64": attr.label(
default = "@bun_linux_aarch64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_linux_x64": attr.label(
default = "@bun_linux_x64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_windows_x64": attr.label(
default = "@bun_windows_x64//:bun",
cfg = "exec",
allow_single_file = True,
),
},
)
_wails_bun_frontend_dev = rule(
implementation = _wails_bun_frontend_dev_impl,
attrs = {
"data": attr.label_list(allow_files = True),
"node_modules": attr.label(
mandatory = True,
allow_files = True,
),
"package_json": attr.label(
mandatory = True,
allow_single_file = True,
),
"script": attr.string(default = "dev"),
"workspace_dir": attr.string(default = ""),
"_tool": attr.label(
default = "//wails_bun/tools:frontend_dev_server",
cfg = "exec",
executable = True,
),
"_bun_darwin_aarch64": attr.label(
default = "@bun_darwin_aarch64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_darwin_x64": attr.label(
default = "@bun_darwin_x64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_linux_aarch64": attr.label(
default = "@bun_linux_aarch64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_linux_x64": attr.label(
default = "@bun_linux_x64//:bun",
cfg = "exec",
allow_single_file = True,
),
"_bun_windows_x64": attr.label(
default = "@bun_windows_x64//:bun",
cfg = "exec",
allow_single_file = True,
),
},
executable = True,
)
def wails_bun_frontend_dev(
name,
data,
node_modules,
package_json,
script = "dev",
workspace_dir = "",
tags = None,
visibility = None):
_wails_bun_frontend_dev(
name = name,
data = data,
node_modules = node_modules,
package_json = package_json,
script = script,
tags = tags,
visibility = visibility,
workspace_dir = workspace_dir,
)

View File

@@ -0,0 +1,71 @@
"""Macros for Bun-backed Wails applications."""
load("//wails:defs.bzl", "wails_build_assets", "wails_generate_bindings", "wails_run")
load(":private/dev_session.bzl", "wails_bun_dev_session")
load(":private/frontend_dist.bzl", "wails_bun_frontend_dev", "wails_bun_frontend_dist")
def wails_bun_app(
name,
app_binary,
frontend_srcs,
package_json,
node_modules,
build_asset_srcs,
app_name,
binary_name,
icon = None,
bindings_package_dir = ".",
frontend_strip_prefix = "",
build_strip_prefix = "",
visibility = None):
wails_bun_frontend_dist(
name = name + "_frontend_dist",
srcs = frontend_srcs,
node_modules = node_modules,
package_json = package_json,
strip_prefix = frontend_strip_prefix,
visibility = visibility,
)
wails_build_assets(
name = name + "_build_assets",
srcs = build_asset_srcs,
app_name = app_name,
binary_name = binary_name,
strip_prefix = build_strip_prefix,
visibility = visibility,
)
wails_generate_bindings(
name = name + "_bindings",
out_dir = "frontend/src/lib/bindings",
package_dir = bindings_package_dir,
visibility = visibility,
)
wails_bun_frontend_dev(
name = name + "_frontend_dev",
data = frontend_srcs,
node_modules = node_modules,
package_json = package_json,
visibility = visibility,
)
wails_run(
name = name + "_run",
binary = app_binary,
build_assets = name + "_build_assets",
icon = icon,
visibility = visibility,
)
wails_bun_dev_session(
name = name + "_dev",
workspace_dir = native.package_name() or ".",
frontend_dev = name + "_frontend_dev",
app_binary = app_binary,
build_assets = name + "_build_assets",
bindings_target = name + "_bindings",
icon = icon,
visibility = visibility,
)

View File

@@ -0,0 +1,25 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
go_binary(
name = "frontend_dist_action",
srcs = ["frontend_dist_action.go"],
importpath = "github.com/Eriyc/rules_wails/wails_bun/tools/frontend_dist_action",
pure = "off",
visibility = ["//visibility:public"],
)
go_binary(
name = "bun_dev_session",
srcs = ["bun_dev_session.go"],
importpath = "github.com/Eriyc/rules_wails/wails_bun/tools/bun_dev_session",
pure = "off",
visibility = ["//visibility:public"],
)
go_binary(
name = "frontend_dev_server",
srcs = ["frontend_dev_server.go"],
importpath = "github.com/Eriyc/rules_wails/wails_bun/tools/frontend_dev_server",
pure = "off",
visibility = ["//visibility:public"],
)

View File

@@ -0,0 +1,177 @@
package main
import (
"flag"
"fmt"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
)
func main() {
var frontendDev string
var frontendURL string
var readyTimeout time.Duration
var watchTarget string
var workspaceDir string
flag.StringVar(&frontendDev, "frontend-dev", "", "")
flag.StringVar(&frontendURL, "frontend-url", "http://127.0.0.1:9245", "")
flag.DurationVar(&readyTimeout, "ready-timeout", 2*time.Minute, "")
flag.StringVar(&watchTarget, "watch-target", "", "")
flag.StringVar(&workspaceDir, "workspace-dir", ".", "")
flag.Parse()
require(frontendDev != "", "missing --frontend-dev")
require(watchTarget != "", "missing --watch-target")
workspaceRoot := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
if workspaceRoot == "" {
workspaceRoot = "."
}
runfilesDir := resolveRunfilesDir()
frontendCommand := exec.Command(frontendDev)
frontendCommand.Dir = workspaceRoot
frontendCommand.Env = withRunfilesEnv(os.Environ(), runfilesDir)
frontendCommand.Stdout = os.Stdout
frontendCommand.Stderr = os.Stderr
must(frontendCommand.Start())
waitCh := make(chan error, 1)
go func() {
waitCh <- frontendCommand.Wait()
}()
defer terminate(frontendCommand, waitCh)
must(waitForURL(frontendURL, readyTimeout, waitCh))
watchCommand, err := resolveWatchCommand(watchTarget)
must(err)
watchCommand.Dir = workspaceRoot
watchCommand.Env = os.Environ()
watchCommand.Stdout = os.Stdout
watchCommand.Stderr = os.Stderr
watchCommand.Stdin = os.Stdin
if err := watchCommand.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
os.Exit(exitError.ExitCode())
}
panic(err)
}
_ = workspaceDir
}
func resolveRunfilesDir() string {
for _, candidate := range []string{
os.Getenv("RUNFILES_DIR"),
os.Getenv("RUNFILES"),
} {
if candidate != "" {
return candidate
}
}
executablePath, err := os.Executable()
if err != nil {
return ""
}
normalizedPath := filepath.Clean(executablePath)
marker := ".runfiles"
if index := strings.Index(normalizedPath, marker+string(os.PathSeparator)); index >= 0 {
return normalizedPath[:index+len(marker)]
}
if strings.HasSuffix(normalizedPath, marker) {
return normalizedPath
}
return ""
}
func withRunfilesEnv(environment []string, runfilesDir string) []string {
if runfilesDir == "" {
return environment
}
environment = setEnv(environment, "RUNFILES_DIR", runfilesDir)
environment = setEnv(environment, "RUNFILES", runfilesDir)
return environment
}
func setEnv(environment []string, key string, value string) []string {
prefix := key + "="
for index, entry := range environment {
if strings.HasPrefix(entry, prefix) {
environment[index] = prefix + value
return environment
}
}
return append(environment, prefix+value)
}
func waitForURL(url string, timeout time.Duration, waitCh <-chan error) error {
client := http.Client{Timeout: 2 * time.Second}
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
select {
case err := <-waitCh:
if err == nil {
return fmt.Errorf("frontend dev server exited before becoming ready")
}
return fmt.Errorf("frontend dev server exited before becoming ready: %w", err)
default:
}
response, err := client.Get(url)
if err == nil {
response.Body.Close()
if response.StatusCode >= 200 && response.StatusCode < 400 {
return nil
}
}
time.Sleep(250 * time.Millisecond)
}
return fmt.Errorf("frontend dev server did not become ready at %s", url)
}
func resolveWatchCommand(target string) (*exec.Cmd, error) {
for _, candidate := range []string{"ibazel", "bazelisk", "bazel"} {
if _, err := exec.LookPath(candidate); err == nil {
return exec.Command(candidate, "run", target), nil
}
}
return nil, fmt.Errorf("neither ibazel, bazelisk, nor bazel is available in PATH")
}
func terminate(command *exec.Cmd, waitCh <-chan error) {
if command.Process == nil {
return
}
_ = command.Process.Kill()
select {
case <-waitCh:
case <-time.After(2 * time.Second):
}
}
func must(err error) {
if err != nil {
panic(err)
}
}
func require(condition bool, message string) {
if !condition {
panic(message)
}
}

View File

@@ -0,0 +1,139 @@
package main
import (
"flag"
"fmt"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
func main() {
var bunDarwinAarch64 string
var bunDarwinX64 string
var bunLinuxAarch64 string
var bunLinuxX64 string
var bunWindowsX64 string
var packageDir string
var script string
flag.StringVar(&bunDarwinAarch64, "bun-darwin-aarch64", "", "")
flag.StringVar(&bunDarwinX64, "bun-darwin-x64", "", "")
flag.StringVar(&bunLinuxAarch64, "bun-linux-aarch64", "", "")
flag.StringVar(&bunLinuxX64, "bun-linux-x64", "", "")
flag.StringVar(&bunWindowsX64, "bun-windows-x64", "", "")
flag.StringVar(&packageDir, "package-dir", "", "")
flag.StringVar(&script, "script", "dev", "")
flag.Parse()
require(packageDir != "", "missing --package-dir")
bunPath, err := resolveBunBinary(bunDarwinAarch64, bunDarwinX64, bunLinuxAarch64, bunLinuxX64, bunWindowsX64)
must(err)
must(makeAbsolute(&bunPath))
workspaceRoot := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
if workspaceRoot == "" {
returnError("BUILD_WORKSPACE_DIRECTORY is required for frontend dev sessions")
}
packageRoot := filepath.Join(workspaceRoot, filepath.FromSlash(packageDir))
if _, err := os.Stat(filepath.Join(packageRoot, "package.json")); err != nil {
returnError("frontend package.json not found in workspace package dir: " + packageRoot)
}
environment := append([]string{}, os.Environ()...)
environment = setPath(environment, buildPath(workspaceRoot, packageRoot))
command := exec.Command(bunPath, "--bun", "run", script)
command.Dir = packageRoot
command.Env = environment
command.Stdout = os.Stdout
command.Stderr = os.Stderr
command.Stdin = os.Stdin
if err := command.Run(); err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
os.Exit(exitError.ExitCode())
}
panic(err)
}
}
func resolveBunBinary(darwinAarch64 string, darwinX64 string, linuxAarch64 string, linuxX64 string, windowsX64 string) (string, error) {
switch runtime.GOOS + "/" + runtime.GOARCH {
case "darwin/arm64":
return darwinAarch64, nil
case "darwin/amd64":
return darwinX64, nil
case "linux/arm64":
return linuxAarch64, nil
case "linux/amd64":
return linuxX64, nil
case "windows/amd64":
return windowsX64, nil
default:
return "", fmt.Errorf("unsupported Bun exec platform: %s/%s", runtime.GOOS, runtime.GOARCH)
}
}
func buildPath(workspaceRoot string, packageRoot string) string {
entries := make([]string, 0, 4)
for _, candidate := range []string{
filepath.Join(packageRoot, "node_modules", ".bin"),
filepath.Join(workspaceRoot, "node_modules", ".bin"),
os.Getenv("PATH"),
} {
if candidate != "" {
entries = append(entries, candidate)
}
}
return strings.Join(entries, string(os.PathListSeparator))
}
func setPath(environment []string, pathValue string) []string {
return setEnv(environment, "PATH", pathValue)
}
func setEnv(environment []string, key string, value string) []string {
prefix := key + "="
for index, entry := range environment {
if strings.HasPrefix(entry, prefix) {
environment[index] = prefix + value
return environment
}
}
return append(environment, prefix+value)
}
func makeAbsolute(path *string) error {
if filepath.IsAbs(*path) {
return nil
}
absolutePath, err := filepath.Abs(*path)
if err != nil {
return err
}
*path = absolutePath
return nil
}
func returnError(message string) {
fmt.Fprintln(os.Stderr, message)
os.Exit(1)
}
func must(err error) {
if err != nil {
panic(err)
}
}
func require(condition bool, message string) {
if !condition {
panic(message)
}
}

View File

@@ -0,0 +1,423 @@
package main
import (
"bufio"
"encoding/json"
"flag"
"fmt"
"io"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
type manifestEntry struct {
sourcePath string
relativePath string
}
func main() {
var buildScript string
var bunDarwinAarch64 string
var bunDarwinX64 string
var bunLinuxAarch64 string
var bunLinuxX64 string
var bunWindowsX64 string
var manifestPath string
var nodeModulesRoot string
var outDir string
var packageDir string
var sharedNodeModulesRoot string
var workspaceDir string
flag.StringVar(&buildScript, "build-script", "build", "")
flag.StringVar(&bunDarwinAarch64, "bun-darwin-aarch64", "", "")
flag.StringVar(&bunDarwinX64, "bun-darwin-x64", "", "")
flag.StringVar(&bunLinuxAarch64, "bun-linux-aarch64", "", "")
flag.StringVar(&bunLinuxX64, "bun-linux-x64", "", "")
flag.StringVar(&bunWindowsX64, "bun-windows-x64", "", "")
flag.StringVar(&manifestPath, "manifest", "", "")
flag.StringVar(&nodeModulesRoot, "node-modules-root", "", "")
flag.StringVar(&outDir, "out", "", "")
flag.StringVar(&packageDir, "package-dir", ".", "")
flag.StringVar(&sharedNodeModulesRoot, "shared-node-modules-root", "", "")
flag.StringVar(&workspaceDir, "workspace-dir", "", "")
flag.Parse()
require(manifestPath != "", "missing --manifest")
require(nodeModulesRoot != "", "missing --node-modules-root")
require(outDir != "", "missing --out")
require(packageDir != "", "missing --package-dir")
require(sharedNodeModulesRoot != "", "missing --shared-node-modules-root")
bunPath, err := resolveBunBinary(bunDarwinAarch64, bunDarwinX64, bunLinuxAarch64, bunLinuxX64, bunWindowsX64)
must(err)
must(makeAbsolute(&bunPath))
must(makeAbsolute(&manifestPath))
must(makeAbsolute(&nodeModulesRoot))
must(makeAbsolute(&outDir))
must(makeAbsolute(&sharedNodeModulesRoot))
tempRoot, err := os.MkdirTemp("", "rules-wails-frontend-*")
must(err)
defer os.RemoveAll(tempRoot)
stageRoot := filepath.Join(tempRoot, "workspace")
homeDir := filepath.Join(tempRoot, "home")
must(os.MkdirAll(stageRoot, 0o755))
must(os.MkdirAll(homeDir, 0o755))
must(stageManifest(manifestPath, stageRoot))
must(os.MkdirAll(filepath.Join(stageRoot, "node_modules"), 0o755))
must(copyDirectoryContents(nodeModulesRoot, filepath.Join(stageRoot, "node_modules"), true))
sharedBunStore := filepath.Join(sharedNodeModulesRoot, ".bun")
if pathExists(sharedBunStore) {
stageBunStore := filepath.Join(stageRoot, "node_modules", ".bun")
_ = os.RemoveAll(stageBunStore)
must(os.Symlink(sharedBunStore, stageBunStore))
}
must(restoreBunLinks(stageRoot))
must(overlayWorkspacePackages(stageRoot))
must(installWorkspaceAlias(stageRoot, packageDir, workspaceDir))
must(linkPackageNodeModules(stageRoot, packageDir))
packageRoot := stageRoot
if packageDir != "." {
packageRoot = filepath.Join(stageRoot, filepath.FromSlash(packageDir))
}
command := exec.Command(bunPath, "--bun", "run", buildScript)
command.Dir = packageRoot
command.Env = append(os.Environ(),
"HOME="+homeDir,
"PATH="+buildPath(stageRoot, packageRoot),
)
command.Stdout = os.Stdout
command.Stderr = os.Stderr
command.Stdin = os.Stdin
must(command.Run())
must(os.RemoveAll(outDir))
must(os.MkdirAll(outDir, 0o755))
must(copyDirectoryContents(filepath.Join(packageRoot, "dist"), outDir, false))
}
func resolveBunBinary(darwinAarch64 string, darwinX64 string, linuxAarch64 string, linuxX64 string, windowsX64 string) (string, error) {
switch runtime.GOOS + "/" + runtime.GOARCH {
case "darwin/arm64":
return darwinAarch64, nil
case "darwin/amd64":
return darwinX64, nil
case "linux/arm64":
return linuxAarch64, nil
case "linux/amd64":
return linuxX64, nil
case "windows/amd64":
return windowsX64, nil
default:
return "", fmt.Errorf("unsupported Bun exec platform: %s/%s", runtime.GOOS, runtime.GOARCH)
}
}
func overlayWorkspacePackages(stageRoot string) error {
packageRoots := make([]string, 0)
err := filepath.Walk(stageRoot, func(path string, info os.FileInfo, walkErr error) error {
if walkErr != nil {
return walkErr
}
if info.IsDir() && info.Name() == "node_modules" {
return filepath.SkipDir
}
if !info.IsDir() && info.Name() == "package.json" {
packageRoots = append(packageRoots, filepath.Dir(path))
}
return nil
})
if err != nil {
return err
}
for _, packageRoot := range packageRoots {
packageName, err := readPackageName(filepath.Join(packageRoot, "package.json"))
if err != nil || packageName == "" {
continue
}
nodePackageDir := filepath.Join(append([]string{stageRoot, "node_modules"}, strings.Split(packageName, "/")...)...)
if !pathExists(nodePackageDir) {
continue
}
entries, err := os.ReadDir(packageRoot)
if err != nil {
return err
}
for _, entry := range entries {
entryPath := filepath.Join(packageRoot, entry.Name())
destinationPath := filepath.Join(nodePackageDir, entry.Name())
_ = os.RemoveAll(destinationPath)
if err := os.Symlink(entryPath, destinationPath); err != nil {
return err
}
}
}
return nil
}
func restoreBunLinks(stageRoot string) error {
bunPackagesRoot := filepath.Join(stageRoot, "node_modules", ".bun", "node_modules")
if !pathExists(bunPackagesRoot) {
return nil
}
entries, err := os.ReadDir(bunPackagesRoot)
if err != nil {
return err
}
for _, entry := range entries {
entryPath := filepath.Join(bunPackagesRoot, entry.Name())
if strings.HasPrefix(entry.Name(), "@") {
scopeRoot := filepath.Join(stageRoot, "node_modules", entry.Name())
if err := os.MkdirAll(scopeRoot, 0o755); err != nil {
return err
}
scopedEntries, err := os.ReadDir(entryPath)
if err != nil {
return err
}
for _, scopedEntry := range scopedEntries {
scopedPath := filepath.Join(entryPath, scopedEntry.Name())
destinationPath := filepath.Join(scopeRoot, scopedEntry.Name())
_ = os.RemoveAll(destinationPath)
if err := os.Symlink(scopedPath, destinationPath); err != nil {
return err
}
}
continue
}
destinationPath := filepath.Join(stageRoot, "node_modules", entry.Name())
_ = os.RemoveAll(destinationPath)
if err := os.Symlink(entryPath, destinationPath); err != nil {
return err
}
}
return nil
}
func installWorkspaceAlias(stageRoot string, packageDir string, workspaceDir string) error {
if workspaceDir == "" || workspaceDir == "." || workspaceDir == packageDir {
return nil
}
targetPath := stageRoot
if packageDir != "." {
targetPath = filepath.Join(stageRoot, filepath.FromSlash(packageDir))
}
aliasPath := filepath.Join(stageRoot, filepath.FromSlash(workspaceDir))
if err := os.MkdirAll(filepath.Dir(aliasPath), 0o755); err != nil {
return err
}
_ = os.RemoveAll(aliasPath)
return os.Symlink(targetPath, aliasPath)
}
func linkPackageNodeModules(stageRoot string, packageDir string) error {
if packageDir == "." {
return nil
}
packageNodeModules := filepath.Join(stageRoot, filepath.FromSlash(packageDir), "node_modules")
if pathExists(packageNodeModules) {
return nil
}
if err := os.MkdirAll(filepath.Dir(packageNodeModules), 0o755); err != nil {
return err
}
return os.Symlink(filepath.Join(stageRoot, "node_modules"), packageNodeModules)
}
func buildPath(stageRoot string, packageRoot string) string {
entries := make([]string, 0, 3)
for _, candidate := range []string{
filepath.Join(packageRoot, "node_modules", ".bin"),
filepath.Join(stageRoot, "node_modules", ".bin"),
os.Getenv("PATH"),
} {
if candidate != "" {
entries = append(entries, candidate)
}
}
return strings.Join(entries, string(os.PathListSeparator))
}
func stageManifest(manifestPath string, destinationRoot string) error {
entries, err := readManifest(manifestPath)
if err != nil {
return err
}
for _, entry := range entries {
destinationPath := filepath.Join(destinationRoot, filepath.FromSlash(entry.relativePath))
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
return err
}
if err := copyFile(entry.sourcePath, destinationPath); err != nil {
return err
}
}
return nil
}
func readManifest(path string) ([]manifestEntry, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
entries := make([]manifestEntry, 0)
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if line == "" {
continue
}
parts := strings.SplitN(line, "\t", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("invalid manifest line: %s", line)
}
entries = append(entries, manifestEntry{
sourcePath: parts[0],
relativePath: parts[1],
})
}
return entries, scanner.Err()
}
func readPackageName(path string) (string, error) {
file, err := os.Open(path)
if err != nil {
return "", err
}
defer file.Close()
var payload struct {
Name string `json:"name"`
}
if err := json.NewDecoder(file).Decode(&payload); err != nil {
return "", err
}
return payload.Name, nil
}
func copyDirectoryContents(sourceRoot string, destinationRoot string, preserveSymlinks bool) error {
if preserveSymlinks {
copyBinary, err := resolveCopyBinary()
if err != nil {
return err
}
command := exec.Command(copyBinary, "-R", sourceRoot+"/.", destinationRoot+"/")
command.Stdout = os.Stdout
command.Stderr = os.Stderr
return command.Run()
}
return filepath.Walk(sourceRoot, func(path string, info os.FileInfo, walkErr error) error {
if walkErr != nil {
return walkErr
}
relativePath, err := filepath.Rel(sourceRoot, path)
if err != nil {
return err
}
if relativePath == "." {
return nil
}
destinationPath := filepath.Join(destinationRoot, relativePath)
if info.IsDir() {
return os.MkdirAll(destinationPath, 0o755)
}
if err := os.MkdirAll(filepath.Dir(destinationPath), 0o755); err != nil {
return err
}
return copyFile(path, destinationPath)
})
}
func resolveCopyBinary() (string, error) {
for _, candidate := range []string{"/bin/cp", "/usr/bin/cp"} {
if pathExists(candidate) {
return candidate, nil
}
}
return "", fmt.Errorf("unable to locate cp binary for %s/%s", runtime.GOOS, runtime.GOARCH)
}
func copyFile(sourcePath string, destinationPath string) error {
sourceFile, err := os.Open(sourcePath)
if err != nil {
return err
}
defer sourceFile.Close()
destinationFile, err := os.Create(destinationPath)
if err != nil {
return err
}
defer destinationFile.Close()
if _, err := io.Copy(destinationFile, sourceFile); err != nil {
return err
}
return destinationFile.Chmod(0o644)
}
func makeAbsolute(path *string) error {
if filepath.IsAbs(*path) {
return nil
}
absolutePath, err := filepath.Abs(*path)
if err != nil {
return err
}
*path = absolutePath
return nil
}
func pathExists(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func must(err error) {
if err != nil {
panic(err)
}
}
func require(condition bool, message string) {
if !condition {
panic(message)
}
}