blob: 1fb4313f5c4c0cb724a487cc9bb40e9f7e81f271 [file]
# Copyright 2025 The Pigweed Authors
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
# use this file except in compliance with the License. You may obtain a copy of
# the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations under
# the License.
"""A rule for generating the application linker script based on the system
configuration file.
"""
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library")
load("//pw_kernel/tooling:app_linker_script.bzl", "app_linker_script")
def _app_codegen_src_impl(ctx):
output = ctx.actions.declare_file(ctx.attr.name + ".rs")
args = [
"--template",
"app=" + ctx.file.template.path,
"--config",
ctx.file.system_config.path,
"--output",
output.path,
"render-app-template",
]
if ctx.attr.app_name:
args.extend(["--app-name", ctx.attr.app_name])
if ctx.attr.process_name:
args.extend(["--process-name", ctx.attr.process_name])
ctx.actions.run(
inputs = ctx.files.system_config + [ctx.file.template],
outputs = [output],
executable = ctx.executable.system_generator,
mnemonic = "AppCodegenSrc",
arguments = args,
)
return [
DefaultInfo(files = depset([output])),
]
_app_codegen_src = rule(
implementation = _app_codegen_src_impl,
attrs = {
"app_name": attr.string(
doc = "Name of the application in the configuration file.",
default = "",
),
"process_name": attr.string(
doc = "Name of the process in the configuration file.",
default = "",
),
"system_config": attr.label(
doc = "System config file which defines the system.",
allow_single_file = True,
default = "//pw_kernel/target:system_config_file",
),
"system_generator": attr.label(
executable = True,
cfg = "exec",
default = "@pigweed//pw_kernel/tooling/system_generator:system_generator_bin",
),
"template": attr.label(
doc = "Application code generation template file.",
allow_single_file = True,
default = "@pigweed//pw_kernel/tooling/system_generator/templates:app.rs.jinja",
),
},
doc = "Generate the linker script for an app based on the system config.",
)
def rust_app_codegen(name, app_name = "", process_name = None, system_config = None, **kwargs):
"""Wrapper function to generate an app's codegen src and rust library.
Args:
name: The name of the target.
app_name: The name of the app in the system manifest.
process_name: The name of the process in the system manifest.
system_config: System config file which defines the system.
**kwargs: Other attributes (slice edition, tags, target_compatible_with) passed to both the `rust_library` and the internal codegen rule.
"""
tags = kwargs.get("tags", [])
_app_codegen_src(
name = name + ".src",
system_config = system_config,
app_name = app_name,
process_name = process_name if process_name else "",
tags = tags,
)
codegen_kwargs = {}
if "edition" in kwargs:
codegen_kwargs["edition"] = kwargs["edition"]
if "tags" in kwargs:
codegen_kwargs["tags"] = kwargs["tags"]
if "target_compatible_with" in kwargs:
codegen_kwargs["target_compatible_with"] = kwargs["target_compatible_with"]
rust_library(
name = name,
srcs = [":{}.src".format(name)],
deps = [
"@pigweed//pw_kernel/syscall:syscall_defs",
],
**codegen_kwargs
)
def rust_app(name, codegen_crate_name, srcs, deps = None, system_config = None, **kwargs):
"""Wrapper function to generate a userspace rust_binary for the kernel.
Args:
name: The name of the target.
codegen_crate_name: Name to use for the generated codegen crate.
system_config: System config file which defines the system.
srcs: The list of source files for the app.
deps: The list of dependencies for the app.
**kwargs: Other attributes passed to the underlying rules.
"""
if deps == None:
deps = []
rust_app_codegen(
name = codegen_crate_name,
app_name = name,
system_config = system_config,
**kwargs
)
linker_script_name = name + ".linker_script"
tags = kwargs.get("tags", [])
app_linker_script(
name = linker_script_name,
system_config = system_config,
app_name = name,
tags = tags,
)
rust_binary(
name = name,
srcs = srcs,
deps = deps + [
":" + codegen_crate_name,
":" + linker_script_name,
],
**kwargs
)