Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve schema, support 'type', prep for 'headers' (breaking for WORKSPACE) #23

Merged
merged 12 commits into from Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Expand Up @@ -16,7 +16,7 @@ jobs:
[
".",
"examples/module",
"examples/target-determinator"
"examples/workspace"
]
# we only support Bazel 7, and only with bzlmod enabled
exclude: |
Expand All @@ -31,5 +31,5 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- working-directory: examples/target-determinator
- working-directory: examples/workspace
run: ./minimal_download_test.sh
41 changes: 39 additions & 2 deletions .github/workflows/release_prep.sh
Expand Up @@ -18,12 +18,49 @@ git archive --format=tar --prefix=${PREFIX}/ "${stash_name}" | gzip > $ARCHIVE
SHA=$(shasum -a 256 $ARCHIVE | awk '{print $1}')

cat << EOF
## Using Bzlmod with Bazel 6
## Using Bzlmod (preferred)

1. Enable with \`common --enable_bzlmod\` in \`.bazelrc\`.
1. Create a multitool.lock.json ([schema](https://github.com/theoremlp/rules_multitool/blob/main/lockfile.schema.json))
2. Add to your \`MODULE.bazel\` file:

\`\`\`starlark
bazel_dep(name = "rules_multitool", version = "${TAG:1}")

multitool = use_extension("@rules_multitool//multitool:extension.bzl", "multitool")
multitool.hub(lockfile = "//:multitool.lock.json")
use_repo(multitool, "multitool")
\`\`\`

## Using WORKSPACE
1. Create a multitool.lock.json ([schema](https://github.com/theoremlp/rules_multitool/blob/main/lockfile.schema.json))
2. Add to your \`WORKSPACE\` file:

\`\`\`starlark
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")

http_archive(
name = "bazel_features",
sha256 = "06f02b97b6badb3227df2141a4b4622272cdcd2951526f40a888ab5f43897f14",
strip_prefix = "bazel_features-1.9.0",
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v1.9.0/bazel_features-v1.9.0.tar.gz",
)

http_archive(
name = "rules_multitool",
sha256 = "${SHA}",
strip_prefix = "rules_multitool-${TAG:1}",
url = "https://github.com/bazel-contrib/bazel_features/releases/download/v${TAG:1}/bazel_features-${TAG:1}.tar.gz",
)

load("@bazel_features//:deps.bzl", "bazel_features_deps")

bazel_features_deps()

load("@rules_multitool//multitool:multitool.bzl", "multitool")

multitool(
name = "multitool",
lockfile = "//:multitool.lock.json",
)
\`\`\`
EOF
3 changes: 2 additions & 1 deletion MODULE.bazel
Expand Up @@ -6,7 +6,8 @@ module(
compatibility_level = 1,
)

bazel_dep(name = "bazel_skylib", version = "1.4.1")
bazel_dep(name = "bazel_features", version = "1.9.0")
bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "buildifier_prebuilt", version = "6.1.2")
bazel_dep(name = "platforms", version = "0.0.8")

Expand Down
2 changes: 1 addition & 1 deletion examples/module/.bazelversion
@@ -1 +1 @@
7.0.0
7.0.2
2 changes: 1 addition & 1 deletion examples/module/MODULE.bazel
@@ -1,7 +1,7 @@
"multitool example using target-determinator"

module(
name = "multitool_examples__target_determinator",
name = "multitool_examples__module",
version = "0.0.0",
compatibility_level = 1,
)
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions examples/workspace/.bazelversion
@@ -0,0 +1 @@
7.0.2
@@ -1,11 +1,12 @@
"multitool example using target-determinator"

module(
name = "multitool_examples__target_determinator",
name = "multitool_examples__workspace",
version = "0.0.0",
compatibility_level = 1,
)

bazel_dep(name = "bazel_features", version = "1.9.0")
bazel_dep(name = "rules_multitool", version = "0.0.0")
local_path_override(
module_name = "rules_multitool",
Expand Down
@@ -1,3 +1,7 @@
load("@bazel_features//:deps.bzl", "bazel_features_deps")

bazel_features_deps()

load("@rules_multitool//multitool:multitool.bzl", "multitool")

multitool(
Expand Down
141 changes: 106 additions & 35 deletions lockfile.schema.json
@@ -1,41 +1,112 @@
{
"$id": "https://github.com/theoremlp/rules_multitool/lockfile.schema.json",
"title": "Describes binaries and instructions for fetching them under Bazel",
"$id": "https://github.com/theoremlp/rules_multitool/lockfile.schema.json",
"title": "Describes binaries and instructions for fetching them under Bazel",
"type": "object",
"definitions": {
"supported_os": {
"enum": ["macos", "linux"]
},
"supported_cpu": {
"enum": ["x86_64", "arm64"]
},
"file_type": {
"type": "object",
"properties": {
"kind": { "enum": ["file"] },
"url": { "type": "string" },
"sha256": { "type": "string" },
"os": { "$ref": "#/definitions/supported_os" },
"cpu": { "$ref": "#/definitions/supported_cpu" },
"headers": {
"type": "object",
"docs": "headers to pass to the downloader (supported on Bazel >= 7.1.0)",
"additionalProperties": {
"type": "string"
}
}
},
"required": ["kind", "url", "os", "cpu"]
},
"archive_type": {
"type": "object",
"properties": {
"kind": { "enum": ["archive"] },
"url": { "type": "string" },
"sha256": { "type": "string" },
"file": {
"type": "string",
"docs": "archive root relative path to binary"
},
"os": { "$ref": "#/definitions/supported_os" },
"cpu": { "$ref": "#/definitions/supported_cpu" },
"headers": {
"type": "object",
"docs": "headers to pass to the downloader (supported on Bazel >= 7.1.0)",
"additionalProperties": {
"type": "string"
}
},
"type": {
"enum": [
"zip",
"jar",
"war",
"aar",
"tar",
"tar.gz",
"tgz",
"tar.xz",
"txz",
".tar.zst",
".tzst",
"tar.bz2",
".tbz",
".ar",
".deb"
]
}
},
"required": ["kind", "url", "os", "cpu", "file"]
},
"pkg_type": {
"type": "object",
"properties": {
"kind": { "enum": ["pkg"] },
"url": { "type": "string" },
"sha256": { "type": "string" },
"file": {
"type": "string",
"docs": "pkg archive root relative path to binary"
},
"os": { "$ref": "#/definitions/supported_os" },
"cpu": { "$ref": "#/definitions/supported_cpu" },
"headers": {
"type": "object",
"docs": "headers to pass to the downloader (supported on Bazel >= 7.1.0)",
"additionalProperties": {
"type": "string"
}
}
},
"required": ["kind", "url", "os", "cpu", "file"]
}
},
"properties": {
"$schema": { "type": "string" }
},
"additionalProperties": {
"type": "object",
"properties": {
"$schema": { "type": "string" }
},
"additionalProperties": {
"type": "object",
"properties": {
"binaries": {
"type": "array",
"items": {
"type": "object",
"properties": {
"kind": {
"enum": ["file", "archive", "pkg"]
},
"url": {
"type": "string"
},
"file": {
"type": "string",
"description": "when kind is archive or pkg, relative path to the binary within it"
},
"sha256": {
"type": "string"
},
"os": {
"enum": ["macos", "linux"]
},
"cpu": {
"enum": ["x86_64", "arm64"]
}
},
"additionalProperties": false
}
}
"binaries": {
"type": "array",
"items": {
"anyOf": [
{ "$ref": "#/definitions/file_type" },
{ "$ref": "#/definitions/archive_type" },
{ "$ref": "#/definitions/pkg_type" }
]
}
}
}
}
}
2 changes: 1 addition & 1 deletion multitool/extension.bzl
@@ -1,4 +1,4 @@
"multitool"
"multitool module extension"

load("//multitool/private:multitool.bzl", _hub = "hub")

Expand Down
22 changes: 19 additions & 3 deletions multitool/multitool.bzl
@@ -1,5 +1,21 @@
"multitool"
"multitool workspace macros"

load("//multitool/private:multitool.bzl", _multitool = "multitool")
load("//multitool/private:multitool.bzl", "hub")

multitool = _multitool
def multitool(name, lockfile = None, lockfiles = None):
"""(non-bzlmod) Create a multitool hub and register its toolchains.

Args:
name: resulting "hub" repo name to load tools from
lockfile: a label for a lockfile, see /lockfile.schema.json
lockfiles: a list of labels of multiple lockfiles

Note: exactly one of lockfile or lockfiles may be set.
"""
if (not lockfile and not lockfiles) or (lockfile and lockfiles):
fail("Exactly one of lockfile and lockfiles must be set")

lockfiles = lockfiles if lockfiles else [lockfile]

hub(name, lockfiles)
native.register_toolchains("@{name}//toolchains:all".format(name = name))
35 changes: 14 additions & 21 deletions multitool/private/multitool.bzl
Expand Up @@ -39,11 +39,11 @@ of the toolchain definitions in the latter repos to make the dependencies run ex
This implementation depends on rendering a number of templates, which are defined in sibling
folders and managed by the templates starlark file.

To maintain support both bzlmod and non-bzlmod setups, we provide two entrypoints to the rule:
- (bzlmod) hub : invoked by the hub tag in extension.bzl
- (non-bzlmod) multitool : invoked in WORKSPACE or related macros, and additionally registers toolchains
Note that we intend to support both bzlmod and non-bzlmod setups, so `hub` intentionally avoids
a register_toolchains call.
"""

load("@bazel_features//:features.bzl", "bazel_features")
load(":templates.bzl", "templates")

_SUPPORTED_ENVS = [
Expand Down Expand Up @@ -90,6 +90,13 @@ def _load_tools(rctx):

return tools

def _feature_sensitive_args(binary):
args = {}
if bazel_features.external_deps.download_has_headers_param:
args["headers"] = binary.get("headers", {})

return args

def _env_specific_tools_impl(rctx):
tools = _load_tools(rctx)

Expand All @@ -110,6 +117,7 @@ def _env_specific_tools_impl(rctx):
sha256 = binary["sha256"],
output = target_executable,
executable = True,
**_feature_sensitive_args(binary)
)
elif binary["kind"] == "archive":
archive_path = "tools/{tool_name}/{os}_{cpu}_archive".format(
Expand All @@ -122,6 +130,8 @@ def _env_specific_tools_impl(rctx):
url = binary["url"],
sha256 = binary["sha256"],
output = archive_path,
type = binary.get("type", ""),
**_feature_sensitive_args(binary)
)

# link to the executable
Expand All @@ -147,6 +157,7 @@ def _env_specific_tools_impl(rctx):
url = binary["url"],
sha256 = binary["sha256"],
output = archive_path + ".pkg",
**_feature_sensitive_args(binary)
)

rctx.execute([pkgutil_cmd, "--expand-full", archive_path + ".pkg", archive_path])
Expand Down Expand Up @@ -231,21 +242,3 @@ def hub(name, lockfiles):
cpu = env[1],
)
_multitool_hub(name = name, lockfiles = lockfiles)

def multitool(name, lockfile = None, lockfiles = None):
"""(non-bzlmod) Create a multitool hub and register its toolchains.

Args:
name: resulting "hub" repo name to load tools from
lockfile: a label for a lockfile, see /lockfile.schema.json
lockfiles: a list of labels of multiple lockfiles
"""
if lockfile and lockfiles:
fail("Only one of lockfile and lockfiles may be set")
if not lockfile and not lockfiles:
fail("Exactly one of lockfile and lockfiles must be set")
if lockfile:
hub(name, [lockfile])
else:
hub(name, lockfiles)
native.register_toolchains("@{name}//toolchains:all".format(name = name))
12 changes: 9 additions & 3 deletions readme.md
Expand Up @@ -4,9 +4,9 @@ An ergonomic approach to defining a single tool target that resolves to a matchi

## Usage

For a quickstart, see the [bzlmod example](examples/module/).
For a quickstart, see the [module example](examples/module/) or [workspace example](examples/workspace/).

Define a lockfile that references the tools to load:
Define a [lockfile](lockfile.schema.json) that references the tools to load:

```json
{
Expand Down Expand Up @@ -43,7 +43,9 @@ The lockfile supports the following binary kinds:

Save your lockfile and ensure the file is exported using `export_files` so that it's available to Bazel.

Once your lockfile is defined, load the ruleset in your **MODULE.bazel** and create a hub that refers to your lockfile:
### Bazel Module Usage

Once your lockfile is defined, load the ruleset in your MODULE.bazel and create a hub that refers to your lockfile:

```python
bazel_dep(name = "rules_multitool", version = "0.0.0")
Expand All @@ -54,3 +56,7 @@ use_repo(multitool, "multitool")
```

Tools may then be accessed using `@multitool//tools/tool-name`.

### Workspace Usage

Instructions for using with WORKSPACE may be found in [release notes](https://github.com/theoremlp/rules_multitool/releases).