Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 40 additions & 47 deletions powershell/extensions.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,6 @@ load(
"powershell_tools_repository",
)

def _find_modules(module_ctx):
root = None
for mod in module_ctx.modules:
if mod.is_root:
return mod

return root

def _format_toolchain_url(url, version, platform, artifact):
major_minor, _, _ = version.rpartition(".")

Expand All @@ -28,49 +20,50 @@ def _format_toolchain_url(url, version, platform, artifact):
)

def _powershell_impl(module_ctx):
root = _find_modules(module_ctx)
reproducible = True

for attrs in root.tags.toolchain:
if attrs.version not in POWERSHELL_VERSIONS:
fail("Powershell toolchain hub `{}` was given unsupported version `{}`. Try: {}".format(
attrs.name,
attrs.version,
POWERSHELL_VERSIONS.keys(),
))
available = POWERSHELL_VERSIONS[attrs.version]
toolchain_names = []
toolchain_labels = {}
target_compatible_with = {}
for platform, artifact_info in available.items():
tool_name = powershell_tools_repository(
name = "{}__{}".format(attrs.name, platform),
version = attrs.version,
platform = platform,
urls = [
_format_toolchain_url(
url = url,
version = attrs.version,
platform = platform,
artifact = artifact_info["artifact"],
)
for url in attrs.urls
],
integrity = artifact_info["integrity"],
)
# Process all modules, not just the root
for mod in module_ctx.modules:
for attrs in mod.tags.toolchain:
if attrs.version not in POWERSHELL_VERSIONS:
fail("Powershell toolchain hub `{}` was given unsupported version `{}`. Try: {}".format(
attrs.name,
attrs.version,
POWERSHELL_VERSIONS.keys(),
))
available = POWERSHELL_VERSIONS[attrs.version]
toolchain_names = []
toolchain_labels = {}
target_compatible_with = {}
for platform, artifact_info in available.items():
tool_name = powershell_tools_repository(
name = "{}__{}".format(attrs.name, platform),
version = attrs.version,
platform = platform,
urls = [
_format_toolchain_url(
url = url,
version = attrs.version,
platform = platform,
artifact = artifact_info["artifact"],
)
for url in attrs.urls
],
integrity = artifact_info["integrity"],
)

toolchain_names.append(tool_name)
toolchain_labels[tool_name] = "@{}".format(tool_name)
target_compatible_with[tool_name] = CONSTRAINTS[platform]
toolchain_names.append(tool_name)
toolchain_labels[tool_name] = "@{}".format(tool_name)
target_compatible_with[tool_name] = CONSTRAINTS[platform]

powershell_toolchain_repository_hub(
name = attrs.name,
toolchain_labels = toolchain_labels,
toolchain_names = toolchain_names,
exec_compatible_with = {},
target_compatible_with = target_compatible_with,
target_settings = {},
)
powershell_toolchain_repository_hub(
name = attrs.name,
toolchain_labels = toolchain_labels,
toolchain_names = toolchain_names,
exec_compatible_with = {},
target_compatible_with = target_compatible_with,
target_settings = {},
)

return module_ctx.extension_metadata(
reproducible = reproducible,
Expand Down
16 changes: 16 additions & 0 deletions powershell/private/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

TOOLCHAIN_TYPE = str(Label("//powershell:toolchain_type"))

def _rlocationpath(file, workspace_name):
if file.short_path.startswith("../"):
return file.short_path[len("../"):]
return "{}/{}".format(workspace_name, file.short_path)

def _pwsh_toolchain_impl(ctx):
all_files = []
if DefaultInfo in ctx.attr.pwsh:
Expand All @@ -10,10 +15,16 @@ def _pwsh_toolchain_impl(ctx):
ctx.attr.pwsh[DefaultInfo].default_runfiles.files,
])

make_variable_info = platform_common.TemplateVariableInfo({
"PWSH": ctx.executable.pwsh.path,
"PWSH_RLOCATIONPATH": _rlocationpath(ctx.executable.pwsh, ctx.workspace_name),
})

return [
platform_common.ToolchainInfo(
pwsh = ctx.executable.pwsh,
all_files = depset(transitive = all_files),
make_variable_info = make_variable_info,
),
]

Expand Down Expand Up @@ -96,7 +107,12 @@ def _current_pwsh_toolchain_impl(ctx):
toolchain = ctx.toolchains[TOOLCHAIN_TYPE]

return [
DefaultInfo(
files = toolchain.all_files,
runfiles = ctx.runfiles(transitive_files = toolchain.all_files),
),
toolchain,
toolchain.make_variable_info,
]

current_pwsh_toolchain = rule(
Expand Down
7 changes: 7 additions & 0 deletions powershell/runfiles/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
load("//powershell:defs.bzl", "pwsh_library")

pwsh_library(
name = "runfiles",
srcs = ["Runfiles/Runfiles.psm1"],
visibility = ["//visibility:public"],
)
57 changes: 57 additions & 0 deletions powershell/runfiles/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# PowerShell Runfiles Library

This library provides a PowerShell implementation of the Bazel runfiles mechanism, allowing PowerShell scripts to locate data dependencies at runtime.

## Usage

### In a PowerShell Binary or Test

To use the runfiles library in your PowerShell script, you need to:

1. Add the runfiles library as a dependency
2. Use `using module Runfiles` at the top of your script
3. Create a runfiles instance and use it to resolve paths

#### Example

**BUILD.bazel:**

```python
load("@rules_powershell//powershell:defs.bzl", "pwsh_binary")

pwsh_binary(
name = "my_script",
srcs = ["my_script.ps1"],
data = ["data/config.txt"],
deps = ["@rules_powershell//powershell/runfiles"],
)
```

**my_script.ps1:**

```powershell
using module Runfiles

param()

$ErrorActionPreference = "Stop"

# Create a runfiles instance
$runfiles = [Runfiles]::Create()

# Resolve a runfile path
$configPath = $runfiles.Rlocation("my_workspace/data/config.txt")

if ($configPath -and (Test-Path $configPath)) {
$config = Get-Content $configPath
Write-Host "Config: $config"
} else {
Write-Error "Could not find config file"
}
```

## Notes

- When using classes from PowerShell modules, you must use `using module ModuleName` instead of `Import-Module ModuleName`
- The `using` statement must appear at the very top of the script, before any other code (including `param()` blocks)
- The runfiles library works both as a regular module and when embedded into scripts by the build system
Loading
Loading