Skip to content

Commit

Permalink
Install Uapi/shield crate to staging (#10)
Browse files Browse the repository at this point in the history
- [x] create local registry at startup
- [x] remove nigthly cargo
- [x] install uapi
- [x] install shield
- [x] install deps (kconfig, metadata)
- [x] install task
- [x] relink task
  • Loading branch information
fvalette-ledger authored Dec 20, 2024
2 parents bc142c7 + 235fddd commit c7c89e5
Show file tree
Hide file tree
Showing 14 changed files with 402 additions and 98 deletions.
11 changes: 11 additions & 0 deletions doc/commands/internals/cargo_config.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
`cargo_config`
==============

.. argparse::
:module: outpost.barbican._internals.cargo_config
:func: argument_parser
:prog: barbican --internal cargo_config

.. seealso::

:py:mod:`outpost.barbican._internals.cargo_config` module documentation
11 changes: 11 additions & 0 deletions doc/commands/internals/cargo_install.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
`cargo_install`
===============

.. argparse::
:module: outpost.barbican._internals.cargo_install
:func: argument_parser
:prog: barbican --internal cargo_install

.. seealso::

:py:mod:`outpost.barbican._internals.cargo_install` module documentation
52 changes: 52 additions & 0 deletions src/outpost/barbican/_internals/cargo_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# SPDX-FileCopyrightText: 2024 Ledger SAS
#
# SPDX-License-Identifier: Apache-2.0

"""Generate a .cargo/config.toml per cargo app.
Add target specific and per apps compile flags in a config.
"""

from argparse import ArgumentParser
from pathlib import Path
import typing as T


def run_cargo_config(rustargs: Path, target: Path, extra_args: str, outdir: Path) -> None:
rust_target = target.read_text().splitlines()[0]
rust_flags = rustargs.read_text().splitlines()
rust_flags.extend(extra_args.split(" "))
linker_args = list(filter(lambda x: x.startswith("-Clinker"), rust_flags))
linker = linker_args[0].split("=")[1] if len(linker_args) else "is not set"
rust_flags = list(filter(lambda x: not x.startswith("-Clinker"), rust_flags))

config = f"""
[build]
target = "{rust_target}"
target-dir = "{str(outdir.resolve())}"
rustflags = {rust_flags}
[target.{rust_target}]
{"#" if not len(linker_args) else ""}linker = "{linker}"
[env]
OUT_DIR = "{str(outdir.resolve())}"
"""

(outdir / ".cargo" / "config.toml").write_text(config)


def argument_parser() -> ArgumentParser:
parser = ArgumentParser()
parser.add_argument("--rustargs-file", type=Path, help="rustargs file path")
parser.add_argument("--target-file", type=Path, help="rust target file path")
parser.add_argument("--extra-args", type=str)
parser.add_argument("outdir", type=Path, help="output directory")

return parser


def run(argv: T.List[str]) -> None:
"""Execute gen crate cargo config command."""
args = argument_parser().parse_args(argv)
run_cargo_config(args.rustargs_file, args.target_file, args.extra_args, args.outdir)
39 changes: 39 additions & 0 deletions src/outpost/barbican/_internals/cargo_install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-FileCopyrightText: 2024 Ledger SAS
#
# SPDX-License-Identifier: Apache-2.0

"""Generate a .cargo/config.toml per cargo app.
Add target specific and per apps compile flags in a config.
"""

from argparse import ArgumentParser
from pathlib import Path
import typing as T

from .install import run_install, argument_parser as install_argument_parser


def argument_parser() -> ArgumentParser:
parser = install_argument_parser()
parser.add_argument(
"--target-file",
type=Path,
help="rust target file",
)
parser.add_argument(
"--profile",
action="store",
type=str,
default="release",
help="cargo build profile",
)

return parser


def run(argv: T.List[str]) -> None:
args = argument_parser().parse_args(argv)
target: str = args.target_file.read_text().splitlines()[0]
from_dir: Path = (args.from_dir / target / args.profile).resolve(strict=True)
run_install(from_dir, args.files, args.suffix)
4 changes: 3 additions & 1 deletion src/outpost/barbican/_internals/gen_task_metadata_bin.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,4 +105,6 @@ def argument_parser() -> ArgumentParser:
def run(argv: T.List[str]) -> None:
args = argument_parser().parse_args(argv)
# XXX: use builddir as option
run_gen_task_metadata_bin(args.input, args.output, ProjectPath.load(args.projectdir / "build"))
run_gen_task_metadata_bin(
args.input, args.output, ProjectPath.load(args.projectdir / "output" / "build")
)
59 changes: 37 additions & 22 deletions src/outpost/barbican/barbican.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,21 @@
from .logger import logger, log_config
from . import config
from .package import Package, create_package, Backend
from .package.kernel import Kernel
from .package.runtime import Runtime
from .package.meson import Meson
from .package.cargo import Cargo
from .package import cargo

from .buildsys import ninja_backend
from .utils import pathhelper
from .utils import pathhelper, working_directory


class Project:
def __init__(self, project_dir: pathlib.Path) -> None:
self.path = pathhelper.ProjectPath(
project_dir=project_dir,
output_dir=project_dir,
output_dir=project_dir / "output",
)

# XXX:
Expand All @@ -58,18 +61,12 @@ def __init__(self, project_dir: pathlib.Path) -> None:
# This will be, likely, false for next devel step.

# Instantiate Sentry kernel
self._packages.append(
Meson("kernel", self, self._toml["kernel"], Package.Type.Kernel) # type: ignore
)
self._kernel = Kernel(self, self._toml)
self._packages.append(self._kernel._package)

# Instantiate libshield
self._packages.append(
Meson(
"runtime",
self,
self._toml["runtime"],
Package.Type.Runtime, # type: ignore[arg-type]
)
)
self._runtime = Runtime(self, self._toml)
self._packages.append(self._runtime._package)

if "application" in self._toml:
self._noapp = False
Expand All @@ -95,6 +92,15 @@ def update(self) -> None:
p.update()

def setup(self) -> None:

logger.info("Create Cargo local repository")
registry = cargo.LocalRegistry(
self.path.sysroot_data_dir / "cargo" / "registry" / "outpost_sdk"
)
cargo_config = cargo.Config(self.path.output_dir, registry)
registry.init()
self._kernel.install_crates(registry, cargo_config)
self._runtime.install_crates(registry, cargo_config)
logger.info(f"Generating {self.name} Ninja build File")
ninja = ninja_backend.NinjaGenFile(os.path.join(self.path.build_dir, "build.ninja"))

Expand All @@ -112,7 +118,7 @@ def setup(self) -> None:
)

ninja.add_meson_rules()
ninja.add_cargo_rules()
ninja.add_cargo_rules(self._kernel.rustargs, self._kernel.rust_target)

# Add setup/compile/install targets for meson packages
for p in self._packages:
Expand Down Expand Up @@ -143,20 +149,22 @@ def setup(self) -> None:

# Dummy link, for non pic application
for package in self._packages:
if package.is_application and package.backend == Backend.Meson:
ninja.add_relink_meson_target(
# if package.is_application and package.backend == Backend.Meson:
if package.is_application:
ninja.add_relink_target(
package.name,
package.installed_targets[0],
package.dummy_linked_targets[0],
dummy_linker_script,
package_name=package.name if package.backend == Backend.Meson else "kernel",
)

layout_sys_exelist = []
layout_app_exelist = []
for package in self._packages:
if package.is_sys_package:
layout_sys_exelist.extend(package.installed_targets)
elif package.backend == Backend.Meson:
else:
layout_app_exelist.extend(package.dummy_linked_targets)

firmware_layout = ninja.add_internal_gen_memory_layout_target(
Expand All @@ -174,7 +182,7 @@ def setup(self) -> None:

# gen_ld/relink/gen_meta/objcopy app(s)
for package in self._packages:
if package.is_application and package.backend == Backend.Meson:
if package.is_application:
# XXX: Handle multiple exe package
elf_in = package.installed_targets[0]
elf_out = package.relocated_targets[0]
Expand All @@ -189,15 +197,21 @@ def setup(self) -> None:
pathlib.Path(firmware_layout[0]),
package.name,
)
ninja.add_relink_meson_target(
ninja.add_relink_target(
package.name,
elf_in,
elf_out,
linker_script,
package.name,
package_name=package.name if package.backend == Backend.Meson else "kernel",
)

ninja.add_objcopy_rule(elf_out, hex_out, "ihex", [], package.name)
ninja.add_objcopy_rule(
elf_out,
hex_out,
"ihex",
[],
package_name=package.name if package.backend == Backend.Meson else "kernel",
)
app_hex_files.append(hex_out)

ninja.add_gen_metadata_rule(
Expand Down Expand Up @@ -238,7 +252,8 @@ def update(project: Project) -> None:


def setup(project: Project) -> None:
project.setup()
with working_directory(project.path.output_dir):
project.setup()


def common_argument_parser() -> ArgumentParser:
Expand Down
46 changes: 39 additions & 7 deletions src/outpost/barbican/buildsys/ninja_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def add_gen_ldscript_target(
},
)

def add_relink_meson_target(
def add_relink_target(
self,
name: str,
orig_elf: Path,
Expand Down Expand Up @@ -271,16 +271,19 @@ def add_meson_rules(self) -> None:
"touch $out",
)

def add_cargo_rules(self) -> None:
def add_cargo_rules(self, rustargs: Path, rust_target: Path) -> None:
self._ninja.newline()
self._ninja.variable("cargo", find_program("cargo"))
self._ninja.variable("rustargs", str(rustargs.resolve()))
self._ninja.variable("rust_target", str(rust_target.resolve()))
self._ninja.newline()
self._ninja.rule(
"cargo_compile",
description="cargo compile $name",
pool="console",
command="$cargo build -Z unstable-options --manifest-path=$sourcedir/Cargo.toml "
"--target-dir=$builddir --out-dir=$builddir && touch $out",
command="cd $builddir "
+ " && config=$config $cargo build --manifest-path=$sourcedir/Cargo.toml --release"
+ " && touch $out && cd -",
)
self._ninja.newline()
self._ninja.rule(
Expand All @@ -291,6 +294,26 @@ def add_cargo_rules(self) -> None:
)

def add_cargo_package(self, package: "Package") -> None:
self._ninja.newline()
self._ninja.build(
f"{package.build_dir}/.cargo/config.toml",
"internal",
variables={
"cmd": "cargo_config",
"args": f"--rustargs-file={str(package._parent._kernel.rustargs)} "
+ f"--target-file={str(package._parent._kernel.rust_target)} "
+ '--extra-args="'
+ " ".join(package.build_options)
+ '" '
+ f"{str(package.build_dir)}",
"description": f"cargo config {package.name}",
},
order_only=[f"{dep}_install.stamp" for dep in package.deps],
)
self._ninja.newline()
self._ninja.build(
f"{package.name}_setup", "phony", f"{package.build_dir}/.cargo/config.toml"
)
self._ninja.newline()
self._ninja.build(
f"{package.name}_compile.stamp",
Expand All @@ -299,19 +322,28 @@ def add_cargo_package(self, package: "Package") -> None:
"sourcedir": package.src_dir,
"builddir": package.build_dir,
"name": package.name,
"config": package._dotconfig,
},
implicit=f"{package.name}_setup",
)
self._ninja.newline()
self._ninja.build(f"{package.name}_compile", "phony", f"{package.name}_compile.stamp")
self._ninja.newline()

# XXX:
# Cargo binary are built w/o .elf extension that is required here
# so split provides name and pass extension as suffix for install rule

self._ninja.build(
f"{package.name}_install.stamp",
"internal",
implicit=f"{package.name}_compile",
variables={
"cmd": "install",
"args": f"--suffix=.elf {str(package.build_dir)} "
+ " ".join((str(t) for t in package.installed_targets)), # noqa: W503
"cmd": "cargo_install",
"args": "--suffix=.elf "
+ f"--target-file={str(package._parent._kernel.rust_target)} "
+ f"{str(package.build_dir)} "
+ " ".join((str(t.with_suffix("")) for t in package.installed_targets)),
"description": f"cargo install {package.name}",
},
)
Expand Down
Loading

0 comments on commit c7c89e5

Please sign in to comment.