Builtin Functions
The contents of this page can be generated using:
spaces docsSpaces Built-in Functions API Documentation
Table of Contents
Rule Options
Platforms
All rules can be run on a list of platforms (default is all). Specify a platform as:
macos-aarch64macos-x86_64linux-aarch64linux-x86_64windows-aarch64windows-x86_64
Rule Types
Checkout: Assigned by default to all checkout rulesSetup: Assign to a run rule to make all other run rules depend on itRun: Runs when running//:allOptional: Runs if specifical executed or depended on
Inspect (evaluate) scripts without executing rules:
# show rules with a `help` entry
spaces inspect --has-help
# show all rules
spaces --verbosity=message inspect
# show all rules with all details
spaces --verbosity=debug inspectCheckout Rules
You use checkout rules to build a workspace. You can fetch git repositories and archives. You can also add assets (local files) to the workspace root folder (not under version control).
abort
def abort(message) -> NoneAbort script evaluation with a message.
message: Abort message to show the user.
Example
checkout.abort("Failed to do something")add_archive
def add_archive(rule, archive) -> NoneAdds an archive to the workspace.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
archive: dict valueurl: url to zip|tar.xz|tar.gz|tar.bz2 file (can also be an uncompressed file with no suffix)sha256: hash of the filelink: None|Hard: create hardlinks of the archive from the spaces store to the workspaceglobs: optional list of globs prefix with+to include and-to excludestrip_prefix: optional prefix to strip from the archive pathadd_prefix: optional prefix to add in the workspace (e.g. sysroot/share)
Example
checkout.add_archive(
# the rule name is the path in the workspace where the archive will be extracted
rule = {"name": "llvm-project"},
archive = {
"url": "https://github.com/llvm/llvm-project/archive/refs/tags/llvmorg-{}.zip".format(version),
"sha256": "27b5c7c745ead7e9147c78471b9053d4f6fc3bed94baf45f4e8295439f564bb8",
"link": "Hard",
"strip_prefix": "llvm-project-llvmorg-{}".format(version),
"add_prefix": "llvm-project",
},
)add_asset
def add_asset(rule, asset) -> NoneAdds a file to the workspace. This is useful for providing a top-level build file that orchestrates the entire workspace. It can also be used to create a top-level README how the workflow works.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
asset: dict withcontent: file contents as a stringdestination: relative path where asset will live in the workspace
Example
content = """
# README
This is how to use this workspace.
"""
checkout.add_asset(
rule = {"name": "README.md"},
asset = {
"destination": "README.md",
"content": content,
},
)add_cargo_bin
def add_cargo_bin(rule, cargo_bin) -> strAdds a binary crate using cargo-binstall. The binaries are installed in the spaces store and hardlinked to the workspace.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
cargo_bin: dict withcrate: The name of the binary crateversion: The crate version to installbins: List of binaries to install
Example
checkout.add_cargo_bin(
rule = {"name": "probe-rs-tools"},
cargo_bin = {
"crate": "probe-rs-tools",
"version": "0.24.0",
"bins": ["probe-rs", "cargo-embed", "cargo-flash"]
},
)add_hard_link_asset
def add_hard_link_asset(rule, asset) -> NoneAdds a hardlink from anywhere on the system to the workspace
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
asset: dict withsource: the source of the hard linkdestination: relative path where asset will live in the workspace
Example
checkout.add_hard_link_asset(
rule = { "name": "which_pkg_config" },
asset = {
"source": "<path to asset>",
"destination": "sysroot/asset/my_asset"
}
)add_platform_archive
def add_platform_archive(rule, platforms) -> NoneAdds an archive to the workspace based on the platform.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
platforms: dict with platform keysmacos-aarch64: dict with same entries as archive in add_archive()macos-x86_64: same as macos-aarch64windows-aarch64: same as macos-aarch64windows-x86_64: same as macos-aarch64linux-aarch64: same as macos-aarch64linux-x86_64: same as macos-aarch64
Example
base = {
"add_prefix": "sysroot/bin",
"strip_prefix": "target/release",
"link": "Hard",
}
macos_x86_64 = base | {
"url": "https://github.com/work-spaces/spaces/releases/download/v0.6.0-beta.13/spaces-macos-latest-x86_64-v0.6.0-beta.13.zip",
"sha256": "47d325145e6f7f870426f1b123c781f89394b0458bb43f5abe2d36ac3543f7ef",
}
macos_aarch64 = base | {
"url": "https://github.com/work-spaces/spaces/releases/download/v0.6.0-beta.13/spaces-macos-latest-aarch64-v0.6.0-beta.13.zip",
"sha256": "6dd972454942faa609670679c53b6876ab8e66bcfd0b583ee5a8d13c93b2e879",
}
windows_x86_64 = base | {
"url": "https://github.com/work-spaces/spaces/releases/download/v0.6.0-beta.13/spaces-windows-latest-x86_64-v0.6.0-beta.13.exe",
"sha256": "b93dc96b2c66fcfc4aef851db2064f6e6ecb54b29968ca5174f6b892b99651c8",
}
windows_aarch64 = base | {
"url": "https://github.com/work-spaces/spaces/releases/download/v0.6.0-beta.13/spaces-windows-latest-aarch64-v0.6.0-beta.13.exe",
"sha256": "c67c7b23897e0949843e248465d5444428fb287f89dcd45cec76dde4b2cdc6a9",
}
linux_x86_64 = base | {
"url": "https://github.com/work-spaces/spaces/releases/download/v0.6.0-beta.13/spaces-linux-gnu-x86_64-v0.6.0-beta.13.zip",
"sha256": "39030124f18b338eceee09061fb305b522ada76f6a0562f9926ea0747b3ad440",
}
checkout.add_platform_archive(
# rule name is only the path in the workspace if add_prefix is not set
rule = {"name": "spaces"},
platforms = {
"macos-x86_64": macos_x86_64,
"macos-aarch64": macos_aarch64,
"windows-x86_64": windows_x86_64,
"windows-aarch64": windows_aarch64,
"linux-x86_64": linux_x86_64,
},
)add_repo
def add_repo(rule, repo) -> strreturns the name of the current platform
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
repo: dict withurl: ssh or https path to repositoryrev: repository revision as a branch, tag or commitcheckout: Revision: checkout detached at commit or branch|NewBranch: create a new branch based at revclone: Default|Worktree|Shallowis_evaluate_spaces_modules: True|False to check the repo for spaces.star files to evaluate
Example
checkout.add_repo(
# the rule name is also the path in the workspace where the clone will be
rule = { "name": "spaces" },
repo = {
"url": "https://github.com/work-spaces/spaces",
"rev": "main",
"checkout": "Revision",
"clone": "Default",
"is_evaluate_spaces_modules": True
}
)add_soft_link_asset
def add_soft_link_asset(rule, asset) -> NoneAdds a softlink from anywhere on the system to the workspace
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
asset: dict withsource: the source of the software linkdestination: relative path where asset will live in the workspace
Example
checkout.add_hard_link_asset(
rule = { "name": "which_pkg_config" },
asset = {
"source": "<path to asset>",
"destination": "sysroot/asset/my_asset"
}
)add_target
def add_target(rule) -> NoneAdds a target. There is no specific action for the target, but this rule can be useful for organizing dependencies.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
Example
checkout.add_target(
rule = {"name": "my_rule", "deps": ["my_other_rule"]},
)add_which_asset
def add_which_asset(rule, asset) -> NoneAdds a hardlink to an executable file available on the PATH
when checking out the workspace. This is useful for building tools that have complex dependencies.
Avoid using this when creating a workspace for your project. It creates system dependencies
that break workspace hermicity.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
asset: dict withwhich: name of system executable to search fordestination: relative path where asset will live in the workspace
Example
checkout.add_which_asset(
rule = { "name": "which_pkg_config" },
asset = {
"which": "pkg-config",
"destination": "sysroot/bin/pkg-config"
}
)update_asset
def update_asset(rule, asset) -> NoneCreates or updates an existing file containing structured data in the workspace. This rules supports json|toml|yaml files. Different rules can update the same file and the content will be preserved (as long as the keys are unique).
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
asset: dict withdestination: path to the asset in the workspaceformat: json|toml|yamlvalue: dict containing the structured data to be added to the asset
Example
cargo_vscode_task = {
"type": "cargo",
"problemMatcher": ["$rustc"],
"group": "build",
}
# Add some VS code tasks
checkout.update_asset(
rule = {"name": "vscode_tasks"},
asset = {
"destination": ".vscode/tasks.json",
"format": "json",
"value": {
"tasks": [
cargo_vscode_task | {
"command": "build",
"args": ["--manifest-path=spaces/Cargo.toml"],
"label": "build:spaces",
},
cargo_vscode_task | {
"command": "install",
"args": ["--path=spaces", "--root=${userHome}/.local", "--profile=dev"],
"label": "install_dev:spaces",
}
],
},
}
)
# tell cargo to use sccache
checkout.update_asset(
rule = {"name": "cargo_config"},
asset = {
"destination": ".cargo/config.toml",
"format": "toml",
"value": {
"build": {"rustc-wrapper": "sccache"},
},
},
)update_env
def update_env(rule, env) -> NoneCreates or updates the environment file in the workspace.
Spaces creates two mechanisms for managing the workspace environment.
- It generates an
envfile that can be sourced from the command line. - When running
spaces runit executes rules using the same environment values.
The rules allows you to add variables and paths to the environment.
At a minimum, your-workspace/sysroot/bin should be added to the path.
In the workspace, you can start a workspace bash shell using:
bash # or the shell of your preference
source envrule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
env: dict withvars: dict of variables to add to the environmentpaths: list of paths required
Example
checkout.update_env(
rule = {"name": "update_env"},
env = {
"paths": [],
"system_paths": ["/usr/bin", "/bin"],
"vars": {
"PS1": '"(spaces) $PS1"',
},
"inherited_vars": ["HOME", "SHELL", "USER"],
},
)Run Rules
You use run rules to execute tasks in the workspace.
abort
def abort(message) -> NoneAbort script evaluation with a message.
message: Abort message to show the user.
Example
run.abort("Failed to do something")add_archive
def add_archive(rule, archive) -> NoneAdds a rule that will archive a directory.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
archive: dict withinput: path to the directory to archivename: name of the archiveversion: archive version (will be part of the filename)driver: The compression driver: tar.gz|tar.bz2|zip|tar.7z|tar.xzplatform: Optionally specify the platformincludes: Optional list of glob patterns applied to the input directory for inclusionexcludes: Optional list of glob patterns applied to the input directory for exclusion
Example
run.add_archive(
rule = {"name": name, "type": "Optional", "deps": ["sysroot-python:venv"]},
archive = {
"input": "build/install",
"name": "my_archive",
"version": "1.0",
"driver": "tar.gz",
},
)add_exec
def add_exec(rule, exec) -> NoneAdds a rule that will execute a process.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
exec: dict withcommand: name of the command to executeargs: optional list of argumentsenv: optional dict of environment variablesworking_directory: optional working directory (default is the workspace)expect: Failure: expect non-zero return code|Success: expect zero return code|Any: don’t check the return coderedirect_stdout: optional file to redirect stdout to
Example
run.add_exec(
rule = {"name": name, "type": "Setup", "deps": ["sysroot-python:venv"]},
exec = {
"command": "pip3",
"args": ["install"] + packages,
},
)add_kill_exec
def add_kill_exec(rule, kill) -> NoneAdds a rule that will kill the execution of another rule.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
kill: dict withsignal: Hup|Int|Quit|Abort|Kill|Alarm|Terminate|User1|User2target: the name of the rule to killexpect: Failure: expect non-zero return code|Success: expect zero return code|Any: don’t check the return code
Example
run.add_exec(
rule = {"name": name, "type": "Setup", "deps": ["sysroot-python:venv"]},
exec = {
"command": "pip3",
"args": ["install"] + packages,
},
)add_target
def add_target(rule) -> NoneAdds a target. There is no specific action for the target, but this rule can be useful for organizing dependencies.
rule: dictname: rule name as stringdeps: list of dependenciesplatforms: optional list of platforms to run on. If not provided, rule will run on all platforms. See above for detailstype: Checkout|Optional|Setup|Run: see above for detailstype: Setup|Run (default)|Optionalhelp: Optional help text show withspaces evaluate
Example
run.add_target(
rule = {"name": "my_rule", "deps": ["my_other_rule"]},
)Workspace Functions
Description
The workspace functions provide information about the workspace
during checkout and run. Workspaces functions are executed immediately. They are not rule definitions.
Functions
get_absolute_path_to_workspace
def get_absolute_path_to_workspace() -> strreturns the absolute path to the workspace
get_build_archive_info
def get_build_archive_info(rule_name, archive) -> dict['archive_path': str, 'sha256_path': str]returns the path to where run.create_archive() creates the sha256 txt file
rule_name: The name of the rule used to create the archivearchive: The archive info used to create the archive
get_digest
def get_digest() -> strreturns the digest of the workspace. This is only meaningful if the workspace is reproducible (which can’t be known until after checkout)
get_env_var
def get_env_var(var) -> strreturns the value of the workspace environment variable
var: The name of the environment variable
get_path_to_build_archive
def get_path_to_build_archive(rule_name, archive) -> strreturns the path to where run.create_archive() creates the output archive
rule_name: The name of the rule used to create the archivearchive: The archive info used to create the archive
get_path_to_build_checkout
def get_path_to_build_checkout() -> strreturns the path to the workspace build folder for the current script
get_path_to_checkout
def get_path_to_checkout() -> strreturns the path where the current script is located in the workspace
get_path_to_log_file
def get_path_to_log_file(name) -> strreturns the relative workspace path to the log file for the target
name: The name of the rule to get the log file
get_path_to_member
def get_path_to_member(member) -> strreturns a string to the workspace member matching the specified requirement (error if not found)
member: The requirements for the memberurl:str: The url of the memberrequired:dict: {‘Revision’: <git/sha256 hash>}|{‘SemVer’:}
is_path_to_member_available
def is_path_to_member_available(member) -> boolreturns true if the workspace satisfies the requirments
member: The requirements for the memberurl:str: The url of the memberrequired:dict: {‘Revision’: <git/sha256 hash>}|{‘SemVer’:}
Info Functions
Description
The info functions provide information about spaces and the platform.
Info functions are executed immediately. They are not rule definitions.
Functions
get_cpu_count
def get_cpu_count() -> intreturns the number of CPUs on the current machine
get_log_divider_string
def get_log_divider_string() -> strreturns a string representing the end of the log header
get_path_to_store
def get_path_to_store() -> strreturns the path to the spaces store (typically $HOME/.spaces/store)
get_platform_name
def get_platform_name() -> strreturns the name of the current platform: macos-aarch64|macos-x86_64|linux-x86_64|linux-aarch64|windows-x86_64|windows-aarch64
get_supported_platforms
def get_supported_platforms() -> list[str]returns a list of the supported platforms
is_ci
def is_ci() -> intreturns true if --ci is passed on the command line
is_platform_linux
def is_platform_linux() -> boolreturns true if platform is linux
is_platform_macos
def is_platform_macos() -> boolreturns true if platform is macos
is_platform_windows
def is_platform_windows() -> boolreturns true if platform is Windows
parse_log_file
def parse_log_file(path) -> dict['header': dict, 'lines': list[str]]Parses the log file header from yaml and puts the lines into an array
path: The path to the spaces log file
set_max_queue_count
def set_max_queue_count(count) -> intsets the maxiumum number of items to queue at one time
count: the maximum number of items to queue at one time
set_minimum_version
def set_minimum_version(version) -> Nonesets the minimum version of spaces required to run the script
version: the minimum version of spaces required to run the script
set_required_semver
def set_required_semver(semver) -> Nonesets the spaces semver required to run the workspace
semver: The semantic version required for this workspace
Spaces Starlark Standard Functions
Description
The spaces starlark standard library includes functions for doing things like accessing the filesystem. The functions in this library are executed immediately.
fs Functions
append_string_to_file
def append_string_to_file(path, content) -> NoneAppends a string to a file. Creates the file if it doesn’t exist.
path: path relative to the workspace rootcontent: contents to write
exists
def exists(path) -> boolChecks if the file/directory exists
path: path relative to the workspace root
is_directory
def is_directory(path) -> boolChecks if a path is a directory
path: path relative to the workspace root
is_file
def is_file(path) -> boolChecks a path is a file
path: path relative to the workspace root
is_symlink
def is_symlink(path) -> boolChecks if a path is a symlink
path: path relative to the workspace root
read_directory
def read_directory(path) -> [str]Reads the entries of a directory
path: path relative to the workspace root
read_file_to_string
def read_file_to_string(path) -> strReads the contents of the file as a string
path: path relative to the workspace root
read_json_to_dict
def read_json_to_dict(path) -> dict with parsed jsonReads and parses a json file
path: path relative to the workspace root
read_toml_to_dict
def read_toml_to_dict(path) -> strReads and parses a toml file
path: path relative to the workspace root
read_yaml_to_dict
def read_yaml_to_dict(path) -> dict with parsed yamlReads and parses a yaml file
path: path relative to the workspace root
write_string_to_file
def write_string_to_file(path, content) -> NoneWrites a string to a file. Truncates the file if it exists. Creates it if it doesn’t.
path: path relative to the workspace rootcontent: contents to write
hash Functions
compute_sha256_from_file
def compute_sha256_from_file(file_path) -> StringComputes the sha256 checksum for the contents of a file and returns the digest as a string.
file_path: path to the file
compute_sha256_from_string
def compute_sha256_from_string(input) -> StringComputes the sha256 checksum of the given string.
input: input string to hash
json Functions
string_to_dict
def string_to_dict(content) -> dictConverts a JSON formatted string to a dict.
content: The JSON string to convert
to_string
def to_string(value) -> dictConverts a dict to a JSON formatted string.
value: The Starlark value to convert
to_string_pretty
def to_string_pretty(value) -> dictConverts a dict to a JSON formatted string (multi-line, idented).
value: The Starlark value to convert
process Functions
exec
def exec(exec) -> dict # with members `status`, `stdout`, and `stderr`Executes a process
exec: dict with memberscommand: name of the command to executeargs: optional list of argumentsenv: optional dict of environment variablesworking_directory: optional working directory (default is the workspace)stdin: optional string to pipe to the process stdin
script Functions
abort
def abort(message) -> NoneAbort execution. Exit with a non-zero code. Print a message to stderr
message: str: abort message.
get_arg
def get_arg(offset) -> strGets the argument at the specified offset (an empty string is returned if the argument doesn’t exist).
offset: int: offset of the argument to get.
get_args
def get_args(offset) -> dictGets the arguments as a dict with ‘ordered’ and ’named’ keys. ordered is a list of arguments that do not contain =, named is a map of key value pairs separated by =.
offset: int: offset of the argument to get.
def print(content) -> NonePrints a string to the stdout. Only use in a script.
content: str: string content to print.
set_exit_code
def set_exit_code(offset) -> noneSets the exit code of the script. Use zero for success and non-zero for failure. This doesn’t exit the script.
offset: int: offset of the argument to get.