diff --git a/.github/workflows/CI_github.yml b/.github/workflows/CI_github.yml index f6a7a02e..71dcb46d 100644 --- a/.github/workflows/CI_github.yml +++ b/.github/workflows/CI_github.yml @@ -4,7 +4,11 @@ on: push: branches: - master + - feature/yocto-layer-compliance pull_request: + branches: + - master + - feature/yocto-layer-compliance paths-ignore: - "**.md" jobs: @@ -20,6 +24,10 @@ jobs: mono_version: [6.12.0.206] branch: [styhead] arch: [x86-64, arm, arm64] + exclude: + # styhead GCC build broken for ARM32 - see README "Removal of support for ARM32" and discussions/234 + - branch: styhead + arch: arm env: name: build-and-test MONO_VERSION: ${{ matrix.mono_version }} @@ -69,7 +77,6 @@ jobs: echo "MACHINE = \"qemu${ARCH}\"" >> conf/local.conf echo "DL_DIR = \"$GITHUB_WORKSPACE/downloads\"" >> conf/local.conf echo "SSTATE_DIR = \"$GITHUB_WORKSPACE/sstate\"" >> conf/local.conf - echo "PREFERRED_VERSION_mono = \"${MONO_VERSION}\"" >> conf/local.conf echo "PREFERRED_VERSION_mono-native = \"${MONO_VERSION}\"" >> conf/local.conf @@ -82,10 +89,19 @@ jobs: echo "BB_NUMBER_THREADS ?= \"\${@oe.utils.cpu_count()}\"" >> conf/local.conf echo "PARALLEL_MAKE ?= \"-j \${@oe.utils.cpu_count()} -l \${@oe.utils.cpu_count()*2}\"" >> conf/local.conf -# - name: Cleaning -# run: | -# . ./${BRANCH}/poky/oe-init-build-env ${BRANCH}/build -# bitbake -c cleanall test-image-mono dotnet dotnet-native + - name: Yocto layer compliance check + if: github.ref == 'refs/heads/feature/yocto-layer-compliance' || github.head_ref == 'feature/yocto-layer-compliance' + run: | + . ./${BRANCH}/poky/oe-init-build-env ${BRANCH}/build + yocto-check-layer --dependency $GITHUB_WORKSPACE/${BRANCH}/poky/meta --dependency $GITHUB_WORKSPACE/${BRANCH}/meta-openembedded/meta-oe -- $GITHUB_WORKSPACE/${BRANCH}/meta-mono + # Flush ALL stale sstate/sysroot from broken host/fxr commits. + # Previous broken builds left host/fxr/10.0.0 in recipe-sysroot-native + # directories. Must clean dotnet + all consumers to get fresh sysroots. + # TODO: remove this step once all matrix jobs have rebuilt successfully. + - name: Clean stale sstate + run: | + . ./${BRANCH}/poky/oe-init-build-env ${BRANCH}/build + bitbake -c cleansstate dotnet dotnet-native python3-clr-loader python3-clr-loader-native dotnet-helloworld python3-pythonnet - name: Building Mono Test Image run: | . ./${BRANCH}/poky/oe-init-build-env ${BRANCH}/build diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 00000000..a4ca445c --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,5 @@ +# Markdownlint config (used by pre-commit and CI) +# https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md +default: true +MD013: false # line length (allow long lines in tables/docs) +MD041: false # first line in file should be top-level heading (FAQ, etc.) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..68965486 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,24 @@ +# Pre-commit hooks: https://pre-commit.com +# Install: pip install pre-commit && pre-commit install +# Run manually: pre-commit run --all-files + +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v5.0.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-merge-conflict + - id: detect-private-key + - id: check-added-large-files + args: [--maxkb=1000] + - id: check-case-conflict + - id: mixed-line-ending + args: [--fix=lf] + + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.42.0 + hooks: + - id: markdownlint + args: [--fix] diff --git a/README.md b/README.md index 620b8a4e..e7d571fc 100644 --- a/README.md +++ b/README.md @@ -19,17 +19,17 @@ Currently (21/10/2024) `styhead` is failing to build GCC for ARM32. As such we'v ## Layer Dependencies -This layer depends on: +The **only mandated dependency** for this layer is OpenEmbedded-Core (meta). Use the same OE-Core branch as this layer (see [Build status](#build-status) for supported branches, e.g. styhead, scarthgap, kirkstone). URI: git://git.openembedded.org/openembedded-core layers: meta -branch: master +branch: match this layer's branch (e.g. styhead, scarthgap, kirkstone) ## Detail For Mono release notes please see [here](https://www.mono-project.com/docs/about-mono/releases) -## Layer Dependencies +## Optional layer dependency (meta-oe) The libgdiplus recipe has a soft dependency on the giflib recipe which is provided by the meta-oe layer. These dependencies can be controlled using the PACKAGECONFIG feature of yocto. libgdiplus @@ -160,6 +160,7 @@ Follow Yocto change submission policy, detailed here, for formatting: * Create an issue on github.com/dynamicdevices/meta-mono * Fork master on github.com/dynamicdevices/meta-mono +* (Optional) Install [pre-commit](https://pre-commit.com/) and run `pre-commit install` so markdown/YAML linting runs automatically before each commit (not in CI). * Commit your changes to your fork referencing the issue number prefixed with # * Create a pull request (PR) to the main repository * Your PR will trigger a number of CI builds which will run tests to ensure nothing is broken. The CI builds must pass for your PR to be merged by a maintainer. If your PR does not build correctly please address and update the PR with a fix. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..fb2cd790 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,15 @@ +# Security + +## Reporting a vulnerability + +If you believe you have found a security vulnerability in the meta-mono layer or its recipes: + +1. **Do not** open a public GitHub issue. +2. Email the maintainer(s) directly. See the [README](README.md) "Maintainer(s) & Patch policy" section for current contact details. +3. Include a clear description of the issue, steps to reproduce, and any impact assessment. + +We will acknowledge your report and work with you to understand and address the issue. We ask that you allow a reasonable time for a fix before any public disclosure. + +## Scope + +This policy applies to the meta-mono layer metadata (recipes, classes, configuration) and to security issues in how the layer builds or configures software. For vulnerabilities in upstream projects (Mono, .NET, libgdiplus, etc.), please follow those projects’ own security reporting guidelines. diff --git a/docs/YOCTO_LAYER_COMPLIANCE.md b/docs/YOCTO_LAYER_COMPLIANCE.md new file mode 100644 index 00000000..7747a11c --- /dev/null +++ b/docs/YOCTO_LAYER_COMPLIANCE.md @@ -0,0 +1,152 @@ +# Yocto Project layer compliance review + +This document reviews what is needed for meta-mono to meet [Yocto Project Compatible](https://www.yoctoproject.org/compatible-registration/) layer requirements. It is a working checklist for the `feature/yocto-layer-compliance` branch. + +## Reference + +- **Registration form:** https://www.yoctoproject.org/compatible-registration/ +- **Dev manual (compatibility):** https://docs.yoctoproject.org/dev-manual/layers.html#making-sure-your-layer-is-compatible-with-yocto-project +- **yocto-check-layer:** Run from build dir: `yocto-check-layer --dependency -- ` +- **Layer index:** https://layers.openembedded.org/ + +--- + +## 1. Registration form checklist (summary) + + +- [ ] **1.** Submitter is YP member or submission sponsored by YP member / OpenEmbedded — We will ask OpenEmbedded to sponsor this submission by DynamicDevices. +- [x] **2.** Layer listed in OpenEmbedded Layers index — [meta-mono on Layer Index](https://layers.openembedded.org/layerindex/branch/master/layer/meta-mono/) +- [x] **3.** README with origin, maintainer, change process, dependencies/versions — README.md has Layer Dependencies, Maintainer, patch/PR policy. +- [x] **4.** SECURITY file (how/where to report security issues) — SECURITY.md added on this branch. +- [ ] **5.** Builds without errors vs OE-Core with only README-stated dependencies — Must be verified per branch (styhead, etc.). +- [ ] **6.** Do not disable/bypass core QA checks (package_qa, yocto-check-layer) — See "INSANE_SKIP and QA" below. +- [x] **7.** Network only in do_fetch, only Bitbake fetcher APIs — No recipes should fetch outside do_fetch; spot-check recipes. +- [x] **8.** Mandated dependency layers have YP Compatible status — Only `meta` (OE-Core) required; OE-Core is the YP reference base layer and has Compatible status ([layer index](https://layers.openembedded.org/layerindex/branch/master/layer/openembedded-core/)). +- [x] **9.** Layer does not change system behaviour without user opt-in — Software layer; no MACHINE/DISTRO set by default. +- [ ] **10.** Passed yocto-check-layer — Run and fix until PASS. +- [ ] ~~**11.** BSP layers follow BSP Developer's Guide — *N/A:* meta-mono is a software layer.~~ +- [ ] ~~**12.** Hardware / distro / recipe metadata separated (no cross-dependency) — *N/A:* Single software layer.~~ +- [ ] ~~**13.** BitBake/OE-Core as components (if build system functionality) — *N/A:* We use OE, don't patch it.~~ +- [ ] ~~**14.** Patches to BitBake/OE-Core submitted upstream — *N/A:* We don't patch them.~~ +- [ ] **15.** Attestation: support OE architecture, layer model, BSP format, YP aims — At submission time. +- [ ] **16.** Recommendations: kernel, toolchain, testing, resulttool — CI already runs builds/tests; document in README if needed. + +--- + +## 2. yocto-check-layer tests (meta-mono as software layer) + +meta-mono is treated as a **software** layer (recipes only). It must pass **COMMON** tests only (no BSP/DISTRO). + +### 2.1 common.test_readme + +- **Requirement:** README exists (case-insensitive), not empty; contains "maintainer", "patch", and at least one email. +- [x] README.md exists and contains "Maintainer(s) & Patch policy", "patch"/"Pull request", and maintainer email. + +### 2.2 common.test_security + +- **Requirement:** Layer (or git repo top-level) has a file named `SECURITY` or `SECURITY.*` (e.g. SECURITY.md), non-empty. +- [x] SECURITY.md added on this branch. + +### 2.3 common.test_parse + +- **Requirement:** `bitbake -p` runs without parse errors. +- [ ] Run with OE-Core + meta-mono (and any README-stated dependencies, e.g. meta-oe if used). + +### 2.4 common.test_show_environment + +- **Requirement:** `bitbake -e` runs without errors. +- [ ] Same as above. + +### 2.5 common.test_world + +- **Requirement:** `bitbake -S none world` succeeds. +- [ ] Must be run; can be slow and may reveal missing dependencies (e.g. meta-oe for libgdiplus/giflib). + +### 2.6 common.test_world_inherit_class + +- **Requirement:** Same world build with `INHERIT="yocto-check-layer"` (extra per-recipe checks). +- [ ] Run after test_world passes. + +### 2.7 common.test_patches_upstream_status + +- **Requirement:** Every `.patch` file has a valid [Patch Upstream Status](https://docs.yoctoproject.org/contributor-guide/recipe-style-guide.html#patch-upstream-status) (e.g. `Upstream-Status: Pending`, `Inappropriate [Yocto specific]`, `Submitted [url]`). +- [ ] Audit all patches under `recipes-*`; ensure each has a correct `Upstream-Status:` line in the header (many have it; some may use wrong case e.g. `Upstream-status` or be missing). + +### 2.8 common.test_signatures + +- **Requirement:** For software layers, this is often skipped by the script; if run, adding the layer must not change task signatures of other layers. +- [ ] Confirmed when running yocto-check-layer. + +### 2.9 common.test_layerseries_compat + +- **Requirement:** Each collection sets `LAYERSERIES_COMPAT_` (e.g. `LAYERSERIES_COMPAT_mono`). +- [x] `conf/layer.conf` has `LAYERSERIES_COMPAT_mono = "styhead"`. Consider adding more series (e.g. scarthgap, kirkstone) if this layer supports them, to match README branch table. + +--- + +## 3. INSANE_SKIP and QA (form item 6) + +The form states: *"All layers in this submission do not disable or otherwise bypass error QA checks as defined as 'core' tests in the package_qa code and the yocto-check-layer script."* + +### Where we disable/bypass (full inventory) + +**conf/layer.conf** — `buildpaths` only (suppress TMPDIR paths in output): + +| Package | Skip | +|---------|------| +| mono-dbg | buildpaths | +| mono-libs-4.5 | buildpaths | +| msbuild | buildpaths | +| msbuild-dev | buildpaths | +| python3-clr-loader | buildpaths | +| python3-pythonnet | buildpaths | + +**recipes-mono/mono/** — `dev-so` on `${PN}-libs` in each versioned .bb (e.g. mono_6.12.0.206.bb); one recipe also has `file-rdeps` on `${PN}`: + +| File | Skips | +|------|--------| +| mono_6.8.0.96.bb, 6.8.0.105, 6.8.0.123, 6.10.0.104, 6.12.0.* (multiple) | `${PN}-libs`: dev-so | +| mono_6.8.0.123.bb | `${PN}`: file-rdeps | +| mono-6.xx.inc | `${PN}-gac`, `${PN}-xbuild`, `${PN}-configuration-crypto`: file-rdeps | + +**recipes-mono/libgdiplus/libgdiplus-common.inc** — `${PN}`: dev-so + +**recipes-mono/dotnet/dotnet.inc** — `${PN}`: already-stripped libdir staticdev textrel dev-so; `${PN}-dbg`: libdir + +**recipes-mono/dotnet-helloworld/dotnet-helloworld_1.0.bb** — `${PN}`: already-stripped, staticdev, buildpaths + +No other QA bypasses (e.g. no PACKAGE_QA, skip flags in other layers) found in meta-mono. + +**Actions:** + +- [ ] Run yocto-check-layer and see if any of these are flagged as disallowed. +- [ ] If `buildpaths` (or others) are required for Mono/.NET build layout, document the justification in README or a comment so the submission can explain a "No" on item 6 if the project still requires them. + +--- + +## 4. Layer index + +- **Requirement:** Layer must be listed in the [OpenEmbedded Layers index](https://layers.openembedded.org/). +- [x] meta-mono is listed: [layerindex/branch/master/layer/meta-mono](https://layers.openembedded.org/layerindex/branch/master/layer/meta-mono/). When applying, confirm the entry still matches repository URL, description, and layer dependencies (e.g. meta, and meta-oe if optional). + +--- + +## 5. Suggested next steps + +- [ ] **Merge this branch** after review (SECURITY.md + this doc). +- [ ] **Audit patches** for correct `Upstream-Status:` (and fix case/typos like `Upstream-status`). +- [ ] **Set up a build** with OE-Core (and meta-oe if needed) for a branch (e.g. styhead), then run: + - `yocto-check-layer --dependency [--dependency ] -- ` +- [ ] **Fix any failing tests** (parse, environment, world, patches, layerseries). +- [ ] **Review INSANE_SKIP** against yocto-check-layer and package_qa; document or remove as needed. +- [ ] **Confirm layer index** entry and registration form answers (membership/sponsorship, attestations). +- [ ] **Submit** the form at https://www.yoctoproject.org/compatible-registration/ when all items are satisfied. + +--- + +## 6. Branch changes (feature/yocto-layer-compliance) + +- **Added:** `SECURITY.md` – security reporting policy. +- **Added:** `docs/YOCTO_LAYER_COMPLIANCE.md` – this review and checklist. + +No changes to layer.conf, README, or recipes in this branch; those can be done in follow-up commits (e.g. LAYERSERIES_COMPAT, patch headers, README tweaks). \ No newline at end of file diff --git a/recipes-mono/dotnet-helloworld/dotnet-helloworld_1.0.bb b/recipes-mono/dotnet-helloworld/dotnet-helloworld_1.0.bb index be548ea9..26490680 100644 --- a/recipes-mono/dotnet-helloworld/dotnet-helloworld_1.0.bb +++ b/recipes-mono/dotnet-helloworld/dotnet-helloworld_1.0.bb @@ -15,6 +15,16 @@ RDEPENDS:${PN}:append = " \ COMPATIBLE_HOST ?= "(x86_64|aarch64|arm).*-linux" +# NuGet MigrationRunner in .NET 6 hardcodes $HOME for migrations dir. +# Override HOME so it's always writable (CI containers often have read-only HOME). +export HOME="${WORKDIR}/dotnet-home" +export DOTNET_CLI_HOME="${WORKDIR}/dotnet-home" +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE="true" +export DOTNET_CLI_TELEMETRY_OPTOUT="1" +export DOTNET_NOLOGO="1" +export NUGET_PACKAGES="${UNPACKDIR}/nuget-packages" +export NUGET_HTTP_CACHE_PATH="${UNPACKDIR}/nuget-http-cache" + SRC_ARCH:aarch64 = "arm64" SRC_ARCH:arm = "arm" SRC_ARCH:x86-64 = "x64" diff --git a/recipes-mono/dotnet/dotnet.inc b/recipes-mono/dotnet/dotnet.inc index 2cacaa9a..fd58e923 100644 --- a/recipes-mono/dotnet/dotnet.inc +++ b/recipes-mono/dotnet/dotnet.inc @@ -38,8 +38,12 @@ do_install() { install -m 0644 ${S}/LICENSE.txt ${D}${datadir}/dotnet install -m 0644 ${S}/ThirdPartyNotices.txt ${D}${datadir}/dotnet + # Install ALL host/fxr versions from the SDK tarball. Microsoft ships + # updated muxer binaries in serviced SDK releases (e.g. SDK 6.0.428 may + # bundle a 10.0.0 muxer), so only copying DOTNET_RUNTIME_VERSION breaks + # the muxer's fxr lookup. install -d ${D}${datadir}/dotnet/host/fxr - cp -r --no-preserve=ownership ${S}/host/fxr/${DOTNET_RUNTIME_VERSION} ${D}${datadir}/dotnet/host/fxr + cp -r --no-preserve=ownership ${S}/host/fxr/* ${D}${datadir}/dotnet/host/fxr/ cp -r --no-preserve=ownership ${S}/sdk ${D}${datadir}/dotnet/ cp -r --no-preserve=ownership ${S}/sdk-manifests ${D}${datadir}/dotnet/ @@ -53,8 +57,19 @@ do_install() { # Hack to fix liblttng-ust dependency issues patchelf --remove-needed liblttng-ust.so.0 ${D}${datadir}/dotnet/shared/Microsoft.NETCore.App/${DOTNET_RUNTIME_VERSION}/libcoreclrtraceptprovider.so + # Symlink libhostfxr.so - prefer DOTNET_RUNTIME_VERSION, fall back to + # whatever the SDK tarball actually ships (muxer version may differ). install -d ${D}${libdir} - ln -rs ${D}${datadir}/dotnet/host/fxr/${DOTNET_RUNTIME_VERSION}/libhostfxr.so ${D}${libdir}/libhostfxr.so + if [ -f ${D}${datadir}/dotnet/host/fxr/${DOTNET_RUNTIME_VERSION}/libhostfxr.so ]; then + ln -rs ${D}${datadir}/dotnet/host/fxr/${DOTNET_RUNTIME_VERSION}/libhostfxr.so ${D}${libdir}/libhostfxr.so + else + for fxr_dir in ${D}${datadir}/dotnet/host/fxr/*/; do + if [ -f "${fxr_dir}libhostfxr.so" ]; then + ln -rs "${fxr_dir}libhostfxr.so" ${D}${libdir}/libhostfxr.so + break + fi + done + fi } do_install:append:x86-64:class-target () { @@ -85,4 +100,25 @@ RRECOMMENDS:dotnet-dev[nodeprrecs] = "1" INSANE_SKIP:${PN} = "already-stripped libdir staticdev textrel dev-so" INSANE_SKIP:${PN}-dbg = "libdir" +# For native builds, replace the dotnet symlink with a wrapper script that +# ensures HOME is always writable. .NET SDK 6 NuGet MigrationRunner.Run() +# unconditionally writes to $HOME/.local/share/NuGet/Migrations *before* +# checking DOTNET_SKIP_FIRST_TIME_EXPERIENCE. In CI containers HOME is +# often read-only, breaking every recipe that invokes dotnet. The wrapper +# fixes this for ALL consumer recipes automatically. +do_install:append:class-native() { + rm -f ${D}${bindir}/dotnet + cat > ${D}${bindir}/dotnet << 'WRAPPER' +#!/bin/sh +export HOME="${DOTNET_CLI_HOME:-${TMPDIR:-/tmp}/dotnet-home}" +mkdir -p "$HOME" 2>/dev/null || true +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true +export DOTNET_CLI_TELEMETRY_OPTOUT=1 +export DOTNET_NOLOGO=1 +SELF_DIR="$(cd "$(dirname "$0")" && pwd)" +exec "${SELF_DIR}/../share/dotnet/dotnet" "$@" +WRAPPER + chmod 0755 ${D}${bindir}/dotnet +} + BBCLASSEXTEND = "native nativesdk" diff --git a/recipes-python/python3-clr-loader/python3-clr-loader.bb b/recipes-python/python3-clr-loader/python3-clr-loader.bb index 73b1f432..7cbc5b94 100644 --- a/recipes-python/python3-clr-loader/python3-clr-loader.bb +++ b/recipes-python/python3-clr-loader/python3-clr-loader.bb @@ -32,6 +32,16 @@ RDEPENDS:${PN} += " \ export NUGET_PACKAGES="${UNPACKDIR}/nuget-packages" export NUGET_HTTP_CACHE_PATH="${UNPACKDIR}/nuget-http-cache" +# NuGet MigrationRunner.Run() in .NET 6 runs BEFORE the skip-first-time +# check, and hardcodes $HOME/.local/share/NuGet/Migrations. In CI +# containers $HOME is often read-only. Override HOME to a writable path +# so NuGet, dotnet CLI, and any other $HOME consumer all get a writable dir. +export HOME="${WORKDIR}/dotnet-home" +export DOTNET_CLI_HOME="${WORKDIR}/dotnet-home" +export DOTNET_SKIP_FIRST_TIME_EXPERIENCE="true" +export DOTNET_CLI_TELEMETRY_OPTOUT="1" +export DOTNET_NOLOGO="1" + # Workaround for dotnet restore issue, define custom proxy in a .bbappend # and/or in layer.conf or local.conf if dotnet restore was failed. # Override DOTNET_HTTP_PROXY and DOTNET_HTTPS_PROXY in layer.conf or local.conf if needed