Initial RK1 media-center image project
This commit is contained in:
Executable
+226
@@ -0,0 +1,226 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||
# shellcheck source=lib.sh
|
||||
. "${SCRIPT_DIR}/lib.sh"
|
||||
|
||||
LOCK_FILE="${RKMEDIA_ROOT}/sources.lock.json"
|
||||
WORK_DIR="${RKMEDIA_ROOT}/out/work"
|
||||
SOURCE_DIR="${RKMEDIA_ROOT}/out/sources"
|
||||
OUTPUT_DIR="${RKMEDIA_ROOT}/out"
|
||||
JOBS="$(nproc)"
|
||||
FETCH=1
|
||||
PACKAGE_VERSION="$(tr -d '[:space:]' < "${RKMEDIA_ROOT}/VERSION")"
|
||||
RUNTIME_PREFIX=/opt/rkmedia
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage: build-media.sh [options]
|
||||
|
||||
--source-dir DIR Locked source checkouts (default: out/sources)
|
||||
--work-dir DIR Build work directory (default: out/work)
|
||||
--output-dir DIR Package output directory (default: out)
|
||||
--jobs N Parallel jobs (default: nproc)
|
||||
--no-fetch Require sources to exist; never access the network
|
||||
--version VERSION Debian package version (default: VERSION file)
|
||||
EOF
|
||||
}
|
||||
|
||||
while (($#)); do
|
||||
case "$1" in
|
||||
--source-dir) [[ $# -ge 2 ]] || die "--source-dir requires a directory"; SOURCE_DIR="$2"; shift 2 ;;
|
||||
--work-dir) [[ $# -ge 2 ]] || die "--work-dir requires a directory"; WORK_DIR="$2"; shift 2 ;;
|
||||
--output-dir) [[ $# -ge 2 ]] || die "--output-dir requires a directory"; OUTPUT_DIR="$2"; shift 2 ;;
|
||||
--jobs) [[ $# -ge 2 ]] || die "--jobs requires a number"; JOBS="$2"; shift 2 ;;
|
||||
--no-fetch) FETCH=0; shift ;;
|
||||
--version) [[ $# -ge 2 ]] || die "--version requires a value"; PACKAGE_VERSION="$2"; shift 2 ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "unknown argument: $1" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[[ "${JOBS}" =~ ^[1-9][0-9]*$ ]] || die "--jobs must be a positive integer"
|
||||
[[ "${PACKAGE_VERSION}" =~ ^[0-9A-Za-z.+:~-]+$ ]] || die "invalid Debian package version: ${PACKAGE_VERSION}"
|
||||
require_arm64_trixie
|
||||
for command_name in cmake git jq meson ninja pkg-config make patch readelf strip; do
|
||||
need_command "${command_name}"
|
||||
done
|
||||
|
||||
SOURCE_DIR="$(absolute_path "${SOURCE_DIR}")"
|
||||
WORK_DIR="$(absolute_path "${WORK_DIR}")"
|
||||
OUTPUT_DIR="$(absolute_path "${OUTPUT_DIR}")"
|
||||
mkdir -p -- "${SOURCE_DIR}" "${WORK_DIR}" "${OUTPUT_DIR}"
|
||||
|
||||
if ((FETCH)); then
|
||||
"${SCRIPT_DIR}/fetch-sources.sh" --lock "${LOCK_FILE}" --dest "${SOURCE_DIR}"
|
||||
fi
|
||||
|
||||
while IFS=$'\t' read -r name commit; do
|
||||
dir="${SOURCE_DIR}/${name}"
|
||||
[[ -d "${dir}/.git" ]] || die "missing locked source: ${dir}"
|
||||
[[ "$(git -C "${dir}" rev-parse HEAD)" == "${commit}" ]] || die "source commit mismatch: ${name}"
|
||||
done < <(jq -r '.sources[] | select(.build == true) | [.name, .commit] | @tsv' "${LOCK_FILE}")
|
||||
|
||||
BUILD_ROOT="${WORK_DIR}/build"
|
||||
BUILD_PREFIX="${WORK_DIR}/prefix"
|
||||
STAGE_DIR="${WORK_DIR}/stage"
|
||||
reset_child_dir "${WORK_DIR}" "${BUILD_ROOT}"
|
||||
reset_child_dir "${WORK_DIR}" "${BUILD_PREFIX}"
|
||||
reset_child_dir "${WORK_DIR}" "${STAGE_DIR}"
|
||||
|
||||
export SOURCE_DATE_EPOCH
|
||||
SOURCE_DATE_EPOCH="$(jq -er '.source_date_epoch' "${LOCK_FILE}")"
|
||||
export CFLAGS="${CFLAGS:--O2 -pipe -ffile-prefix-map=${WORK_DIR}=. -fdebug-prefix-map=${WORK_DIR}=.}"
|
||||
export CXXFLAGS="${CXXFLAGS:--O2 -pipe -ffile-prefix-map=${WORK_DIR}=. -fdebug-prefix-map=${WORK_DIR}=.}"
|
||||
export LDFLAGS="${LDFLAGS:-}"
|
||||
|
||||
log "building MPP"
|
||||
cmake -S "${SOURCE_DIR}/mpp" -B "${BUILD_ROOT}/mpp" -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="${BUILD_PREFIX}" \
|
||||
-DCMAKE_INSTALL_LIBDIR=lib \
|
||||
-DBUILD_SHARED_LIBS=ON \
|
||||
-DBUILD_TEST=OFF
|
||||
cmake --build "${BUILD_ROOT}/mpp" --parallel "${JOBS}"
|
||||
cmake --install "${BUILD_ROOT}/mpp"
|
||||
|
||||
log "building RGA"
|
||||
meson setup "${BUILD_ROOT}/rga" "${SOURCE_DIR}/rga" \
|
||||
--prefix="${BUILD_PREFIX}" \
|
||||
--libdir=lib \
|
||||
--buildtype=release \
|
||||
--default-library=shared \
|
||||
-Dcpp_args=-fpermissive \
|
||||
-Dlibdrm=false \
|
||||
-Dlibrga_demo=false
|
||||
meson compile -C "${BUILD_ROOT}/rga" -j "${JOBS}"
|
||||
meson install -C "${BUILD_ROOT}/rga"
|
||||
|
||||
log "building dav1d"
|
||||
meson setup "${BUILD_ROOT}/dav1d" "${SOURCE_DIR}/dav1d" \
|
||||
--prefix="${BUILD_PREFIX}" \
|
||||
--libdir=lib \
|
||||
--buildtype=release \
|
||||
--default-library=shared \
|
||||
-Denable_tools=false \
|
||||
-Denable_tests=false \
|
||||
-Denable_examples=false \
|
||||
-Denable_docs=false
|
||||
meson compile -C "${BUILD_ROOT}/dav1d" -j "${JOBS}"
|
||||
meson install -C "${BUILD_ROOT}/dav1d"
|
||||
|
||||
export PKG_CONFIG_PATH="${BUILD_PREFIX}/lib/pkgconfig${PKG_CONFIG_PATH:+:${PKG_CONFIG_PATH}}"
|
||||
export LD_LIBRARY_PATH="${BUILD_PREFIX}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
||||
|
||||
log "building FFmpeg-Rockchip"
|
||||
mkdir -p -- "${BUILD_ROOT}/ffmpeg"
|
||||
pushd "${BUILD_ROOT}/ffmpeg" >/dev/null
|
||||
"${SOURCE_DIR}/ffmpeg-rockchip/configure" \
|
||||
--prefix="${BUILD_PREFIX}" \
|
||||
--libdir="${BUILD_PREFIX}/lib" \
|
||||
--enable-shared \
|
||||
--disable-static \
|
||||
--disable-debug \
|
||||
--disable-doc \
|
||||
--enable-pic \
|
||||
--enable-gpl \
|
||||
--enable-version3 \
|
||||
--enable-libdrm \
|
||||
--enable-rkmpp \
|
||||
--enable-rkrga \
|
||||
--enable-libdav1d \
|
||||
--extra-cflags="-I${BUILD_PREFIX}/include" \
|
||||
--extra-ldflags="-L${BUILD_PREFIX}/lib -Wl,-rpath,${RUNTIME_PREFIX}/lib"
|
||||
make -j "${JOBS}"
|
||||
make install
|
||||
popd >/dev/null
|
||||
|
||||
FFMPEG_BUILD="${BUILD_PREFIX}/bin/ffmpeg"
|
||||
for decoder in h264_rkmpp hevc_rkmpp vp9_rkmpp av1_rkmpp mjpeg_rkmpp; do
|
||||
"${FFMPEG_BUILD}" -hide_banner -decoders 2>/dev/null | awk '{print $2}' | grep -Fxq "${decoder}" \
|
||||
|| die "FFmpeg is missing decoder ${decoder}"
|
||||
done
|
||||
for encoder in h264_rkmpp hevc_rkmpp mjpeg_rkmpp; do
|
||||
"${FFMPEG_BUILD}" -hide_banner -encoders 2>/dev/null | awk '{print $2}' | grep -Fxq "${encoder}" \
|
||||
|| die "FFmpeg is missing encoder ${encoder}"
|
||||
done
|
||||
for filter in scale_rkrga vpp_rkrga overlay_rkrga; do
|
||||
"${FFMPEG_BUILD}" -hide_banner -filters 2>/dev/null | awk '{print $2}' | grep -Fxq "${filter}" \
|
||||
|| die "FFmpeg is missing filter ${filter}"
|
||||
done
|
||||
|
||||
log "building libdisplay-info"
|
||||
meson setup "${BUILD_ROOT}/libdisplay-info" "${SOURCE_DIR}/libdisplay-info" \
|
||||
--prefix="${BUILD_PREFIX}" \
|
||||
--libdir=lib \
|
||||
--buildtype=release \
|
||||
--default-library=shared
|
||||
meson compile -C "${BUILD_ROOT}/libdisplay-info" -j "${JOBS}"
|
||||
meson install -C "${BUILD_ROOT}/libdisplay-info"
|
||||
|
||||
log "building Kodi for GBM/GLES with external FFmpeg-Rockchip"
|
||||
cmake -S "${SOURCE_DIR}/kodi" -B "${BUILD_ROOT}/kodi" -G Ninja \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_INSTALL_PREFIX="${RUNTIME_PREFIX}" \
|
||||
-DCMAKE_INSTALL_RPATH="${RUNTIME_PREFIX}/lib" \
|
||||
-DCMAKE_BUILD_RPATH="${BUILD_PREFIX}/lib" \
|
||||
-DCMAKE_PREFIX_PATH="${BUILD_PREFIX}" \
|
||||
-DCORE_PLATFORM_NAME=gbm \
|
||||
-DAPP_RENDER_SYSTEM=gles \
|
||||
-DENABLE_INTERNAL_FFMPEG=OFF \
|
||||
-DFFMPEG_PATH="${BUILD_PREFIX}" \
|
||||
-DENABLE_INTERNAL_FMT=ON \
|
||||
-DENABLE_INTERNAL_FLATBUFFERS=ON
|
||||
cmake --build "${BUILD_ROOT}/kodi" --parallel "${JOBS}"
|
||||
|
||||
mkdir -p -- "${STAGE_DIR}${RUNTIME_PREFIX}"
|
||||
cp -a -- "${BUILD_PREFIX}/." "${STAGE_DIR}${RUNTIME_PREFIX}/"
|
||||
DESTDIR="${STAGE_DIR}" cmake --install "${BUILD_ROOT}/kodi"
|
||||
|
||||
log "adding runtime integration and source provenance"
|
||||
cp -a -- "${RKMEDIA_ROOT}/packaging/rootfs/." "${STAGE_DIR}/"
|
||||
mkdir -p -- "${STAGE_DIR}/usr/bin" "${STAGE_DIR}/usr/share/doc/rk1-media-stack/licenses"
|
||||
ln -sfn /opt/rkmedia/bin/ffmpeg-rk "${STAGE_DIR}/usr/bin/ffmpeg-rk"
|
||||
ln -sfn /opt/rkmedia/bin/ffprobe-rk "${STAGE_DIR}/usr/bin/ffprobe-rk"
|
||||
ln -sfn /opt/rkmedia/bin/kodi-rk "${STAGE_DIR}/usr/bin/kodi-rk"
|
||||
install -m 0644 "${LOCK_FILE}" "${STAGE_DIR}/usr/share/doc/rk1-media-stack/sources.lock.json"
|
||||
|
||||
while IFS=$'\t' read -r name license_path; do
|
||||
source_license="${SOURCE_DIR}/${name}/${license_path}"
|
||||
destination="${STAGE_DIR}/usr/share/doc/rk1-media-stack/licenses/${name}"
|
||||
[[ -e "${source_license}" ]] || die "locked license path is missing: ${name}/${license_path}"
|
||||
mkdir -p -- "${destination}"
|
||||
cp -a -- "${source_license}" "${destination}/"
|
||||
done < <(jq -r '.sources[] | select(.build == true) as $source | $source.license_files[] | [$source.name, .] | @tsv' "${LOCK_FILE}")
|
||||
|
||||
rm -rf -- \
|
||||
"${STAGE_DIR}${RUNTIME_PREFIX}/include" \
|
||||
"${STAGE_DIR}${RUNTIME_PREFIX}/lib/pkgconfig" \
|
||||
"${STAGE_DIR}${RUNTIME_PREFIX}/share/pkgconfig"
|
||||
find "${STAGE_DIR}${RUNTIME_PREFIX}" -type f \( -name '*.a' -o -name '*.la' \) -delete
|
||||
|
||||
while IFS= read -r -d '' candidate; do
|
||||
if file --brief "${candidate}" | grep -q '^ELF '; then
|
||||
strip --strip-unneeded "${candidate}" || die "failed to strip ${candidate}"
|
||||
fi
|
||||
done < <(find "${STAGE_DIR}${RUNTIME_PREFIX}" -type f -print0)
|
||||
|
||||
for required in \
|
||||
"${STAGE_DIR}${RUNTIME_PREFIX}/bin/ffmpeg" \
|
||||
"${STAGE_DIR}${RUNTIME_PREFIX}/bin/ffprobe" \
|
||||
"${STAGE_DIR}${RUNTIME_PREFIX}/bin/kodi" \
|
||||
"${STAGE_DIR}/usr/lib/systemd/system/kodi-rk.service"; do
|
||||
[[ -e "${required}" ]] || die "staged runtime file is missing: ${required}"
|
||||
done
|
||||
|
||||
if find "${STAGE_DIR}${RUNTIME_PREFIX}" -type f -exec grep -IlF "${WORK_DIR}" {} + | grep -q .; then
|
||||
die "build path leaked into a staged text file"
|
||||
fi
|
||||
|
||||
"${SCRIPT_DIR}/package-media.sh" \
|
||||
--stage "${STAGE_DIR}" \
|
||||
--output-dir "${OUTPUT_DIR}" \
|
||||
--version "${PACKAGE_VERSION}"
|
||||
|
||||
log "media build complete"
|
||||
Reference in New Issue
Block a user