Skip to content

Commit 33c18e1

Browse files
committed
feat: add openembedded-sdk-builder module
1 parent 3e4db4d commit 33c18e1

File tree

12 files changed

+827
-2
lines changed

12 files changed

+827
-2
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/sdk/** linguist-generated
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/sdk
2+
/.venv
3+
/**/__pycache__
4+
/.env
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"$schema": "https://docs.dagger.io/reference/dagger.schema.json",
3+
"name": "openembedded-sdk-builder",
4+
"engineVersion": "v0.18.10",
5+
"sdk": {
6+
"source": "python"
7+
}
8+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"name": "@skycaptain/daggerverse-openembedded-sdk-builder",
3+
"private": true
4+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Skycaptain: Daggerverse
2+
#
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
#
5+
[project]
6+
name = "skycaptain-daggerverse-openembedded-sdk-builder"
7+
version = "0.0.0"
8+
requires-python = ">=3.12"
9+
dependencies = ["dagger-io"]
10+
11+
[tool.uv.sources]
12+
dagger-io = { path = "sdk", editable = true }
13+
14+
[build-system]
15+
requires = ["hatchling==1.25.0"]
16+
build-backend = "hatchling.build"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Skycaptain: Daggerverse
2+
//
3+
// See https://semantic-release.gitbook.io/ for usage.
4+
//
5+
// SPDX-License-Identifier: BSD-3-Clause
6+
//
7+
// RELEASE BUSTER: 0
8+
//
9+
const packageName = "openembedded-sdk-builder";
10+
11+
/** @type {import('semantic-release').GlobalConfig} */
12+
export default {
13+
extends: "semantic-release-monorepo",
14+
plugins: [
15+
"@semantic-release/commit-analyzer",
16+
"@semantic-release/release-notes-generator",
17+
"@semantic-release/github",
18+
],
19+
preset: "conventionalcommits",
20+
tagFormat: `${packageName}-v\${version}`,
21+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Skycaptain: Daggerverse
2+
#
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
#
5+
from .main import OpenembeddedSdkBuilder as OpenembeddedSdkBuilder
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Skycaptain: Daggerverse
2+
#
3+
# SPDX-License-Identifier: BSD-3-Clause
4+
#
5+
from typing import Self
6+
7+
import dagger
8+
from dagger import dag, field, function, object_type
9+
10+
# FIXME: Add Renovate configuration to lock and update the digests of the refs.
11+
# See https://github.com/renovatebot/renovate/issues/10993
12+
DEFAULT_BUILDER_IMAGE_REF = "python:3.12-bookworm"
13+
DEFAULT_BASE_IMAGE_REF = "mcr.microsoft.com/devcontainers/cpp:bookworm"
14+
15+
SDK_INSTALL_DIR = "/sdk"
16+
17+
18+
@object_type
19+
class OpenembeddedSdkBuilder:
20+
base_image_ref: str = DEFAULT_BASE_IMAGE_REF
21+
22+
sdk_dir: dagger.Directory = field(default=dag.directory)
23+
24+
entrypoint: dagger.File = field(
25+
default=lambda: dag.file(
26+
"entrypoint",
27+
r"""#!/bin/sh
28+
# Source the environment setup file
29+
. "$(find "${SDK_HOME}" -maxdepth 1 -type f -name 'environment-setup-*')"
30+
31+
# Execute CMD
32+
exec "$@"
33+
""",
34+
permissions=0o755,
35+
)
36+
)
37+
38+
@function
39+
async def with_sdk_dir_from_deploy_bin_ref(
40+
self,
41+
ref: str,
42+
*,
43+
builder_image_ref: str = DEFAULT_BUILDER_IMAGE_REF,
44+
platform: dagger.Platform | None = None,
45+
) -> Self:
46+
return await self.with_sdk_dir_from_deploy_bin_ctr(
47+
ctr=dag.container(platform=platform).from_(ref),
48+
builder_image_ref=builder_image_ref,
49+
platform=platform,
50+
)
51+
52+
@function
53+
async def with_sdk_dir_from_deploy_bin_ctr(
54+
self,
55+
ctr: dagger.Container,
56+
*,
57+
builder_image_ref: str = DEFAULT_BUILDER_IMAGE_REF,
58+
platform: dagger.Platform | None = None,
59+
) -> Self:
60+
return await self.with_sdk_dir_from_deploy_bin_dir(
61+
directory=ctr.directory("/"),
62+
platform=platform or await ctr.platform(),
63+
builder_image_ref=builder_image_ref,
64+
)
65+
66+
@function
67+
async def with_sdk_dir_from_deploy_bin_dir(
68+
self,
69+
directory: dagger.Directory,
70+
*,
71+
builder_image_ref: str = DEFAULT_BUILDER_IMAGE_REF,
72+
platform: dagger.Platform | None = None,
73+
) -> Self:
74+
# Find the toolchain installer script in the binaries directory
75+
sdk_installer_path = await directory.glob("**/tmp*/deploy/sdk/*toolchain*.sh")
76+
77+
if len(sdk_installer_path) != 1:
78+
raise ValueError(f"Expected exactly one SDK installer, found {len(sdk_installer_path)}")
79+
80+
self.sdk_dir = (
81+
dag.container(platform=platform)
82+
.from_(builder_image_ref)
83+
.with_mounted_directory("/src", directory)
84+
.with_exec([f"/src/{sdk_installer_path}", "-d", SDK_INSTALL_DIR, "-y"])
85+
.directory(SDK_INSTALL_DIR)
86+
)
87+
88+
return self
89+
90+
@function
91+
async def container(self, platform: dagger.Platform | None = None) -> dagger.Container:
92+
ctr = dag.container(platform=platform).from_(self.base_image_ref)
93+
94+
# Copy the SDK from the builder container
95+
ctr = (
96+
ctr
97+
# Add the installed SDK directory
98+
.with_directory(SDK_INSTALL_DIR, self.sdk_dir)
99+
# Add entrypoint
100+
.with_file("/usr/bin/entrypoint", self.entrypoint, permissions=0o755)
101+
.with_entrypoint(["/usr/bin/entrypoint"])
102+
# The default command when running the container
103+
.with_default_args(["/bin/bash"])
104+
# Export the location of the installed SDK for downstream scripts
105+
.with_env_variable("SDK_HOME", SDK_INSTALL_DIR)
106+
)
107+
108+
# Bake-in OECORE_NATIVE_SYSROOT to make native SDK tools available without executing the
109+
# environment setup script, e.g., when using with a devcontainer
110+
oe_native_sysroot = (
111+
await ctr.with_exec(
112+
["printenv", "OECORE_NATIVE_SYSROOT"],
113+
use_entrypoint=True,
114+
).stdout()
115+
).strip()
116+
if not oe_native_sysroot:
117+
raise ValueError("OECORE_NATIVE_SYSROOT environment variable not found in the SDK")
118+
119+
ctr = ctr.with_env_variable("OECORE_NATIVE_SYSROOT", oe_native_sysroot)
120+
121+
# Find and bake-in the environment setup script, e.g. to ease running tasks in VS Code
122+
env_setup = await ctr.directory(SDK_INSTALL_DIR).glob("environment-setup-*")
123+
if len(env_setup) != 1:
124+
raise ValueError(f"Expected exactly one env setup script, found {len(env_setup)}")
125+
126+
ctr = ctr.with_env_variable("SDK_ENV_SETUP", f"{SDK_INSTALL_DIR}/{env_setup[0]}")
127+
128+
return ctr

0 commit comments

Comments
 (0)