Adopt BSD make ports framework
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
BMAKE ?= bmake
|
||||
|
||||
.PHONY: check
|
||||
|
||||
check:
|
||||
./tests/check-layout.sh
|
||||
@if command -v "$(BMAKE)" >/dev/null 2>&1; then \
|
||||
"$(BMAKE)" -f tests/framework.mk check; \
|
||||
else \
|
||||
printf '%s\n' "bmake parse check skipped: bmake is unavailable"; \
|
||||
fi
|
||||
|
||||
|
Before Width: | Height: | Size: 47 B After Width: | Height: | Size: 239 B |
@@ -1,14 +1,14 @@
|
||||
# MOUSE ports
|
||||
|
||||
This repository is the independently versioned source-port collection for
|
||||
MOUSE. It contains third-party recipes and patches only; the `mouse-port`
|
||||
implementation, ports contract, base-system manifest, and release integration
|
||||
belong to `mouse-src`.
|
||||
MOUSE. Each port is a BSD make project, while shared phase and quality-control
|
||||
machinery lives under `ports/Mk`.
|
||||
|
||||
Each port lives below `ports/NAME` and follows the recipe contract shipped by
|
||||
the compatible MOUSE base release. A MOUSE release pins one tested commit from
|
||||
this repository, while installed systems may move to later compatible ports
|
||||
revisions without replacing the base system.
|
||||
Each port lives below `ports/category/name` and contains a `Makefile`,
|
||||
`distinfo`, and `pkg-plist`, plus optional patches and service definitions
|
||||
under `files`. A MOUSE release pins one tested commit from this repository,
|
||||
while installed systems may move to later compatible ports revisions without
|
||||
replacing the base system.
|
||||
|
||||
The adversarial and demonstration recipes used by the base-system acceptance
|
||||
suite are deliberately not part of this collection. They live in
|
||||
@@ -19,3 +19,16 @@ Run the collection checks with:
|
||||
```sh
|
||||
make check
|
||||
```
|
||||
|
||||
On MOUSE, a port's public interface is:
|
||||
|
||||
```sh
|
||||
make fetch
|
||||
make checksum
|
||||
make build
|
||||
make stage
|
||||
make package
|
||||
make install
|
||||
make deinstall
|
||||
make clean
|
||||
```
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
# Infrastructure
|
||||
|
||||
Collection-wide generation, lint, and publication tooling belongs here. Base
|
||||
image assembly and the `mouse-port` implementation remain in `mouse-src`.
|
||||
Collection-wide generation, lint, and publication tooling belongs here. The
|
||||
live framework is `ports/Mk/mouse.port.mk`, with narrow shell helpers in
|
||||
`ports/Mk/Scripts`.
|
||||
|
||||
Base-manifest enforcement and transactional package registration remain a
|
||||
private base-system responsibility in `mouse-src`.
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
.PHONY: identity list
|
||||
|
||||
identity:
|
||||
@. /etc/mouse-release; \
|
||||
revision=$$(cat /usr/share/mouse/ports.revision); \
|
||||
printf '%s\n' "$$PRETTY_NAME" "ports $$revision"
|
||||
|
||||
list:
|
||||
@/usr/libexec/mouse-package list
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -ne 3 ]; then
|
||||
printf '%s\n' "usage: check-plist.sh STAGEDIR PREFIX PLIST" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
stage=$1
|
||||
prefix=$2
|
||||
plist=$3
|
||||
[ -f "$plist" ] || {
|
||||
printf '%s\n' "missing packing list: $plist" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
normalize() {
|
||||
case "$1" in
|
||||
/*) printf '%s\n' "$1" ;;
|
||||
*) printf '%s/%s\n' "$prefix" "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
while IFS= read -r entry || [ -n "$entry" ]; do
|
||||
case "$entry" in
|
||||
""|\#*) continue ;;
|
||||
esac
|
||||
path=$(normalize "$entry")
|
||||
if [ ! -f "$stage$path" ] && [ ! -L "$stage$path" ]; then
|
||||
printf '%s\n' "packing-list path was not staged: $path" >&2
|
||||
exit 1
|
||||
fi
|
||||
done <"$plist"
|
||||
|
||||
(
|
||||
cd "$stage"
|
||||
find . -mindepth 1 \( -type f -o -type l \) -print
|
||||
) |
|
||||
while IFS= read -r relative; do
|
||||
path=${relative#.}
|
||||
found=0
|
||||
while IFS= read -r entry || [ -n "$entry" ]; do
|
||||
case "$entry" in
|
||||
""|\#*) continue ;;
|
||||
esac
|
||||
normalized=$(normalize "$entry")
|
||||
if [ "$normalized" = "$path" ]; then
|
||||
found=1
|
||||
break
|
||||
fi
|
||||
done <"$plist"
|
||||
[ "$found" -eq 1 ] || {
|
||||
printf '%s\n' "staged path is absent from packing list: $path" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 4 ]; then
|
||||
printf '%s\n' \
|
||||
"usage: checksum.sh DISTDIR DISTINFO SHA256_COMMAND DISTFILE..." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
distdir=$1
|
||||
distinfo=$2
|
||||
sha256_command=$3
|
||||
shift 3
|
||||
[ -f "$distinfo" ] || {
|
||||
printf '%s\n' "missing distinfo: $distinfo" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
for distfile in "$@"; do
|
||||
expected=$(sed -n "s/^SHA256 ($distfile) = //p" "$distinfo")
|
||||
case "$expected" in
|
||||
????????????????????????????????????????????????????????????????) ;;
|
||||
*) printf '%s\n' "invalid or missing checksum for $distfile" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$expected" in
|
||||
*[!0-9a-f]*) printf '%s\n' "invalid checksum for $distfile" >&2; exit 1 ;;
|
||||
esac
|
||||
actual=$("$sha256_command" "$distdir/$distfile")
|
||||
[ "$actual" = "$expected" ] || {
|
||||
printf '%s\n' \
|
||||
"$distfile checksum mismatch: expected $expected, got $actual" >&2
|
||||
exit 1
|
||||
}
|
||||
done
|
||||
Executable
+24
@@ -0,0 +1,24 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 4 ]; then
|
||||
printf '%s\n' \
|
||||
"usage: fetch.sh DISTDIR MASTER_SITES FETCH_COMMAND DISTFILE..." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
distdir=$1
|
||||
master_sites=$2
|
||||
fetch_command=$3
|
||||
shift 3
|
||||
mkdir -p "$distdir"
|
||||
|
||||
for distfile in "$@"; do
|
||||
case "$distfile" in
|
||||
""|*/*) printf '%s\n' "unsafe distfile name: $distfile" >&2; exit 1 ;;
|
||||
esac
|
||||
if [ ! -f "$distdir/$distfile" ]; then
|
||||
"$fetch_command" "$master_sites$distfile" \
|
||||
"$distdir/$distfile"
|
||||
fi
|
||||
done
|
||||
Executable
+37
@@ -0,0 +1,37 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 2 ]; then
|
||||
printf '%s\n' \
|
||||
"usage: install-depends.sh PORTSDIR PACKAGE_COMMAND DEPENDENCY..." >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
portsdir=$1
|
||||
package_command=$2
|
||||
shift 2
|
||||
|
||||
for dependency in "$@"; do
|
||||
case "$dependency" in
|
||||
*:*/*) ;;
|
||||
*) printf '%s\n' "invalid dependency: $dependency" >&2; exit 1 ;;
|
||||
esac
|
||||
name=${dependency%%:*}
|
||||
origin=${dependency#*:}
|
||||
category=${origin%%/*}
|
||||
port=${origin#*/}
|
||||
case "$origin" in
|
||||
*/*/*) printf '%s\n' "invalid dependency origin: $origin" >&2; exit 1 ;;
|
||||
esac
|
||||
for component in "$name" "$category" "$port"; do
|
||||
case "$component" in
|
||||
""|[!a-z]*|*[!a-z0-9-]*)
|
||||
printf '%s\n' "invalid dependency: $dependency" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if ! "$package_command" status "$name" >/dev/null 2>&1; then
|
||||
make -C "$portsdir/$origin" install
|
||||
fi
|
||||
done
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
if [ "$#" -lt 9 ]; then
|
||||
printf '%s\n' \
|
||||
"usage: package.sh PKGDIR STAGEDIR NAME VERSION ORIGIN PLIST DISTINFO MAKEFILE PORTS_REVISION [DEPENDENCY...]" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
package=$1
|
||||
stage=$2
|
||||
name=$3
|
||||
version=$4
|
||||
origin=$5
|
||||
plist=$6
|
||||
distinfo=$7
|
||||
makefile=$8
|
||||
ports_revision=$9
|
||||
shift 9
|
||||
|
||||
case "$name" in
|
||||
""|[!a-z]*|*[!a-z0-9-]*) printf '%s\n' "invalid package name: $name" >&2; exit 1 ;;
|
||||
esac
|
||||
case "$version" in
|
||||
""|*[!A-Za-z0-9._+-]*) printf '%s\n' "invalid package version: $version" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
rm -rf "$package"
|
||||
mkdir -p "$package/root"
|
||||
cp -R "$stage/." "$package/root/"
|
||||
{
|
||||
printf 'name=%s\n' "$name"
|
||||
printf 'version=%s\n' "$version"
|
||||
printf 'origin=%s\n' "$origin"
|
||||
printf 'dependencies='
|
||||
separator=
|
||||
for dependency in "$@"; do
|
||||
case "$dependency" in
|
||||
*:*/*) ;;
|
||||
*) printf '%s\n' "invalid dependency: $dependency" >&2; exit 1 ;;
|
||||
esac
|
||||
dependency_name=${dependency%%:*}
|
||||
dependency_origin=${dependency#*:}
|
||||
category=${dependency_origin%%/*}
|
||||
dependency_port=${dependency_origin#*/}
|
||||
case "$dependency_origin" in
|
||||
*/*/*)
|
||||
printf '%s\n' "invalid dependency origin: $dependency_origin" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
for component in "$dependency_name" "$category" "$dependency_port"; do
|
||||
case "$component" in
|
||||
""|[!a-z]*|*[!a-z0-9-]*)
|
||||
printf '%s\n' "invalid dependency: $dependency" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
printf '%s%s' "$separator" "$dependency_name"
|
||||
separator=" "
|
||||
done
|
||||
printf '\n'
|
||||
} >"$package/+MANIFEST"
|
||||
cp "$plist" "$package/+PLIST"
|
||||
cp "$distinfo" "$package/+DISTINFO"
|
||||
cp "$makefile" "$package/+BUILD"
|
||||
cp "$ports_revision" "$package/+PORTS_REVISION"
|
||||
@@ -0,0 +1,134 @@
|
||||
# Common MOUSE ports framework. Individual ports define metadata and any
|
||||
# port-specific do-build or do-install targets before including this file.
|
||||
|
||||
.if !defined(PORTNAME) || empty(PORTNAME)
|
||||
.error PORTNAME is required
|
||||
.endif
|
||||
.if !defined(PORTVERSION) || empty(PORTVERSION)
|
||||
.error PORTVERSION is required
|
||||
.endif
|
||||
.if !defined(CATEGORIES) || empty(CATEGORIES)
|
||||
.error CATEGORIES is required
|
||||
.endif
|
||||
.if !defined(MASTER_SITES) || empty(MASTER_SITES)
|
||||
.error MASTER_SITES is required
|
||||
.endif
|
||||
.if !defined(DISTFILES) || empty(DISTFILES)
|
||||
.error DISTFILES is required
|
||||
.endif
|
||||
|
||||
.if !defined(PORTSDIR)
|
||||
PORTSDIR:= ${.PARSEDIR:H:tA}
|
||||
.endif
|
||||
PORTDIR?= ${.CURDIR}
|
||||
PORTORIGIN?= ${CATEGORIES}/${PORTNAME}
|
||||
PREFIX?= /usr/local
|
||||
DISTDIR?= /var/cache/mouse/ports/distfiles
|
||||
WRKDIR?= /var/tmp/mouse-ports/${PORTNAME}-${PORTVERSION}
|
||||
WRKSRC?= ${WRKDIR}/source
|
||||
STAGEDIR?= ${WRKDIR}/stage
|
||||
PACKAGES?= /var/cache/mouse/packages
|
||||
PKGNAME?= ${PORTNAME}-${PORTVERSION}
|
||||
PKGDIR?= ${PACKAGES}/${PKGNAME}
|
||||
DISTINFO_FILE?= ${PORTDIR}/distinfo
|
||||
PLIST?= ${PORTDIR}/pkg-plist
|
||||
PORTS_REVISION_FILE?=/usr/share/mouse/ports.revision
|
||||
RUN_DEPENDS?=
|
||||
NO_EXTRACT?= no
|
||||
EXTRACT_CMD?= /usr/bin/tar
|
||||
|
||||
MOUSE_PACKAGE?= /usr/libexec/mouse-package
|
||||
MOUSE_FETCH?= /usr/libexec/mouse-fetch
|
||||
MOUSE_SHA256?= /usr/bin/mouse-sha256
|
||||
MOUSE_SH?= /bin/sh
|
||||
|
||||
FETCH_SCRIPT= ${PORTSDIR}/Mk/Scripts/fetch.sh
|
||||
CHECKSUM_SCRIPT=${PORTSDIR}/Mk/Scripts/checksum.sh
|
||||
PLIST_SCRIPT= ${PORTSDIR}/Mk/Scripts/check-plist.sh
|
||||
DEPENDS_SCRIPT= ${PORTSDIR}/Mk/Scripts/install-depends.sh
|
||||
PACKAGE_SCRIPT= ${PORTSDIR}/Mk/Scripts/package.sh
|
||||
|
||||
.PHONY: all fetch checksum extract configure build stage stage-qa package \
|
||||
install deinstall status clean do-extract do-configure do-build do-install
|
||||
.MAIN: all
|
||||
|
||||
all: build
|
||||
|
||||
fetch:
|
||||
${MOUSE_SH} ${FETCH_SCRIPT} "${DISTDIR}" "${MASTER_SITES}" \
|
||||
"${MOUSE_FETCH}" ${DISTFILES}
|
||||
|
||||
checksum: fetch
|
||||
${MOUSE_SH} ${CHECKSUM_SCRIPT} "${DISTDIR}" "${DISTINFO_FILE}" \
|
||||
"${MOUSE_SHA256}" ${DISTFILES}
|
||||
|
||||
extract: checksum
|
||||
rm -rf "${WRKDIR}"
|
||||
mkdir -p "${WRKSRC}"
|
||||
.if ${NO_EXTRACT:tl} == "yes"
|
||||
:
|
||||
.else
|
||||
@test -x "${EXTRACT_CMD}" || { \
|
||||
echo "mouse.port.mk: archive extraction requires ${EXTRACT_CMD}" >&2; \
|
||||
false; \
|
||||
}
|
||||
cd "${WRKSRC}" && "${EXTRACT_CMD}" -xf "${DISTDIR}/${DISTFILES}"
|
||||
.endif
|
||||
${MAKE} do-extract
|
||||
|
||||
configure: extract
|
||||
${MAKE} do-configure
|
||||
|
||||
build: configure
|
||||
${MAKE} do-build
|
||||
|
||||
stage: build
|
||||
rm -rf "${STAGEDIR}"
|
||||
mkdir -p "${STAGEDIR}"
|
||||
${MAKE} do-install
|
||||
${MAKE} stage-qa
|
||||
|
||||
stage-qa:
|
||||
${MOUSE_SH} ${PLIST_SCRIPT} "${STAGEDIR}" "${PREFIX}" "${PLIST}"
|
||||
|
||||
package: stage
|
||||
${MOUSE_SH} ${PACKAGE_SCRIPT} "${PKGDIR}" "${STAGEDIR}" \
|
||||
"${PORTNAME}" "${PORTVERSION}" "${PORTORIGIN}" "${PLIST}" \
|
||||
"${DISTINFO_FILE}" "${PORTDIR}/Makefile" \
|
||||
"${PORTS_REVISION_FILE}" ${RUN_DEPENDS}
|
||||
|
||||
install:
|
||||
${MOUSE_SH} ${DEPENDS_SCRIPT} "${PORTSDIR}" "${MOUSE_PACKAGE}" \
|
||||
${RUN_DEPENDS}
|
||||
${MAKE} package
|
||||
${MOUSE_PACKAGE} add "${PKGDIR}"
|
||||
|
||||
deinstall:
|
||||
${MOUSE_PACKAGE} delete "${PORTNAME}"
|
||||
|
||||
status:
|
||||
${MOUSE_PACKAGE} status "${PORTNAME}"
|
||||
|
||||
clean:
|
||||
rm -rf "${WRKDIR}" "${PKGDIR}"
|
||||
|
||||
.if !target(do-extract)
|
||||
do-extract:
|
||||
:
|
||||
.endif
|
||||
|
||||
.if !target(do-configure)
|
||||
do-configure:
|
||||
:
|
||||
.endif
|
||||
|
||||
.if !target(do-build)
|
||||
do-build:
|
||||
:
|
||||
.endif
|
||||
|
||||
.if !target(do-install)
|
||||
do-install:
|
||||
@echo "mouse.port.mk: ${PORTNAME} must define do-install" >&2
|
||||
@false
|
||||
.endif
|
||||
+9
-2
@@ -1,7 +1,14 @@
|
||||
# Ports collection
|
||||
|
||||
Each immediate child directory is one port named `[a-z][a-z0-9-]*` and contains
|
||||
one `port.conf` plus its trusted `build.sh` and any port-owned patches or files.
|
||||
Ports use `category/name` directories. Every ordinary port contains a
|
||||
`Makefile`, `distinfo`, and `pkg-plist`; optional patches and service files live
|
||||
under `files`.
|
||||
|
||||
Every port ends its Makefile with:
|
||||
|
||||
```make
|
||||
.include "${.PARSEDIR}/../../Mk/mouse.port.mk"
|
||||
```
|
||||
|
||||
The collection is intentionally empty until the first real third-party port is
|
||||
accepted. Test-only recipes do not belong here.
|
||||
|
||||
+16
-25
@@ -2,32 +2,23 @@
|
||||
set -eu
|
||||
|
||||
root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
|
||||
found=0
|
||||
|
||||
for directory in "$root"/ports/*; do
|
||||
[ -d "$directory" ] || continue
|
||||
[ "${directory##*/}" != README.md ] || continue
|
||||
found=1
|
||||
name=${directory##*/}
|
||||
case "$name" in
|
||||
""|[!a-z]*|*[!a-z0-9-]*)
|
||||
printf '%s\n' "invalid port directory name: $name" >&2
|
||||
[ -f "$root/ports/Mk/mouse.port.mk" ]
|
||||
[ -x "$root/ports/Mk/Scripts/check-plist.sh" ]
|
||||
[ -x "$root/ports/Mk/Scripts/checksum.sh" ]
|
||||
[ -x "$root/ports/Mk/Scripts/fetch.sh" ]
|
||||
[ -x "$root/ports/Mk/Scripts/install-depends.sh" ]
|
||||
[ -x "$root/ports/Mk/Scripts/package.sh" ]
|
||||
|
||||
find "$root/ports" -mindepth 2 -maxdepth 2 -type d \
|
||||
! -path "$root/ports/Mk/*" -print |
|
||||
while IFS= read -r port; do
|
||||
for file in Makefile distinfo pkg-plist; do
|
||||
[ -f "$port/$file" ] || {
|
||||
printf '%s\n' "missing $file: $port" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
[ -f "$directory/port.conf" ] || {
|
||||
printf '%s\n' "missing recipe: ports/$name/port.conf" >&2
|
||||
exit 1
|
||||
}
|
||||
[ -x "$directory/build.sh" ] || {
|
||||
printf '%s\n' "missing executable build script: ports/$name/build.sh" >&2
|
||||
exit 1
|
||||
}
|
||||
sh -n "$directory/build.sh"
|
||||
}
|
||||
done
|
||||
done
|
||||
|
||||
if [ "$found" -eq 0 ]; then
|
||||
printf '%s\n' "ports collection is empty"
|
||||
else
|
||||
printf '%s\n' "ports layout check passed"
|
||||
fi
|
||||
printf '%s\n' "ports layout checks passed"
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
PORTNAME= framework-test
|
||||
PORTVERSION= 1.0.0
|
||||
CATEGORIES= tests
|
||||
MASTER_SITES= http://example.invalid/
|
||||
DISTFILES= framework-test.c
|
||||
NO_EXTRACT= yes
|
||||
|
||||
.include "${.PARSEDIR}/../ports/Mk/mouse.port.mk"
|
||||
|
||||
check:
|
||||
@test "${PORTNAME}" = framework-test
|
||||
@test "${PORTSDIR}" = "${.CURDIR}/ports"
|
||||
@test "${PORTORIGIN}" = tests/framework-test
|
||||
Reference in New Issue
Block a user