mirror of
https://github.com/InstanceBrick/nightcap.git
synced 2026-10-18 03:01:03 +02:00
277 lines
8.0 KiB
Bash
Executable File
277 lines
8.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Copyright 2026 Mocktail Project Authors
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
set -euo pipefail
|
|
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
BOLD='\033[1m'
|
|
RESET='\033[0m'
|
|
|
|
info() { echo -e "${CYAN}[info]${RESET} $*"; }
|
|
success() { echo -e "${GREEN}[ok]${RESET} $*"; }
|
|
warn() { echo -e "${YELLOW}[warn]${RESET} $*"; }
|
|
die() { echo -e "${RED}[error]${RESET} $*" >&2; exit 1; }
|
|
step() { echo; echo -e "${BOLD}[$*]${RESET}"; }
|
|
|
|
Usage() {
|
|
cat <<'EOF'
|
|
Usage: scripts/build.sh [OPTIONS]
|
|
|
|
With no APK option, this helper builds only the native runtime. The first
|
|
normal launch downloads, validates, canaries, and activates the supported
|
|
Roblox x86_64 payload automatically. The ordinary entry point is `make build`,
|
|
which invokes CMake directly without this helper.
|
|
|
|
Options:
|
|
--apk PATH Explicitly extract a local Roblox x86_64 APK.
|
|
--apk-url URL Explicitly download and extract an APK URL.
|
|
--skip-apk Compatibility alias for managed-payload mode.
|
|
--build-dir PATH CMake build directory (default: build).
|
|
--cmake-toolchain FILE
|
|
Explicit CMake toolchain file.
|
|
--cmake-sysroot DIR Explicit compiler/CMake sysroot.
|
|
--build-type TYPE Debug, Release, or RelWithDebInfo (default: Release).
|
|
--jobs N Parallel build jobs (default: nproc).
|
|
--run-tests Run CTest after building.
|
|
--clean Remove the selected build directory first.
|
|
-h, --help Show this help.
|
|
|
|
Examples:
|
|
make build
|
|
./scripts/build.sh
|
|
./scripts/build.sh --build-type Debug --run-tests
|
|
./scripts/build.sh --apk /path/to/roblox-x86_64.apk
|
|
EOF
|
|
}
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
BUILD_DIR="${PROJECT_ROOT}/build"
|
|
RBX_BIN_DIR="${PROJECT_ROOT}/rbx_bin"
|
|
APK_PATH=""
|
|
APK_URL=""
|
|
EXTRACT_APK=false
|
|
EXPLICIT_RUNTIME_OVERRIDE=false
|
|
BUILD_TYPE="Release"
|
|
JOBS="$(nproc)"
|
|
RUN_TESTS=false
|
|
CLEAN=false
|
|
CMAKE_TOOLCHAIN_FILE=""
|
|
CMAKE_SYSROOT=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--apk)
|
|
[[ $# -ge 2 ]] || die "--apk requires a path"
|
|
APK_PATH="$2"
|
|
EXTRACT_APK=true
|
|
shift 2
|
|
;;
|
|
--apk-url)
|
|
[[ $# -ge 2 ]] || die "--apk-url requires a URL"
|
|
APK_URL="$2"
|
|
EXTRACT_APK=true
|
|
shift 2
|
|
;;
|
|
--skip-apk)
|
|
EXTRACT_APK=false
|
|
shift
|
|
;;
|
|
--build-dir)
|
|
[[ $# -ge 2 ]] || die "--build-dir requires a path"
|
|
BUILD_DIR="$2"
|
|
shift 2
|
|
;;
|
|
--cmake-toolchain)
|
|
[[ $# -ge 2 ]] || die "--cmake-toolchain requires a file"
|
|
CMAKE_TOOLCHAIN_FILE="$2"
|
|
shift 2
|
|
;;
|
|
--cmake-sysroot)
|
|
[[ $# -ge 2 ]] || die "--cmake-sysroot requires a directory"
|
|
CMAKE_SYSROOT="$2"
|
|
shift 2
|
|
;;
|
|
--build-type) BUILD_TYPE="$2"; shift 2 ;;
|
|
--jobs) JOBS="$2"; shift 2 ;;
|
|
--run-tests) RUN_TESTS=true; shift ;;
|
|
--clean) CLEAN=true; shift ;;
|
|
--help|-h)
|
|
Usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
die "Unknown option: $1 (try --help)"
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ "${EXTRACT_APK}" == true && -n "${APK_PATH}" && -n "${APK_URL}" ]]; then
|
|
die "--apk and --apk-url are mutually exclusive"
|
|
fi
|
|
|
|
if [[ "${BUILD_DIR}" != /* ]]; then
|
|
BUILD_DIR="${PROJECT_ROOT}/${BUILD_DIR}"
|
|
fi
|
|
BUILD_DIR="$(readlink -m -- "${BUILD_DIR}")"
|
|
[[ "${BUILD_DIR}" != / && "${BUILD_DIR}" != "${PROJECT_ROOT}" ]] ||
|
|
die "Unsafe build directory: ${BUILD_DIR}"
|
|
if [[ -n "${CMAKE_TOOLCHAIN_FILE}" ]]; then
|
|
[[ -f "${CMAKE_TOOLCHAIN_FILE}" ]] ||
|
|
die "CMake toolchain file not found: ${CMAKE_TOOLCHAIN_FILE}"
|
|
CMAKE_TOOLCHAIN_FILE="$(readlink -f -- "${CMAKE_TOOLCHAIN_FILE}")"
|
|
fi
|
|
if [[ -n "${CMAKE_SYSROOT}" ]]; then
|
|
[[ -d "${CMAKE_SYSROOT}" ]] ||
|
|
die "CMake sysroot not found: ${CMAKE_SYSROOT}"
|
|
CMAKE_SYSROOT="$(cd -P -- "${CMAKE_SYSROOT}" && pwd)"
|
|
fi
|
|
|
|
info "Mocktail build: ${BUILD_TYPE}, -j${JOBS}"
|
|
info "Project root: ${PROJECT_ROOT}"
|
|
info "Build directory: ${BUILD_DIR}"
|
|
|
|
step "1/5 checking dependencies"
|
|
|
|
check_tool() {
|
|
local tool="$1"
|
|
local hint="${2:-install ${tool}}"
|
|
if command -v "${tool}" &>/dev/null; then
|
|
success "${tool} found: $(command -v "${tool}")"
|
|
else
|
|
die "${tool} not found. Hint: ${hint}"
|
|
fi
|
|
}
|
|
|
|
check_tool cmake "install CMake 3.20 or newer"
|
|
if [[ -z "${CMAKE_TOOLCHAIN_FILE}" ]]; then
|
|
check_tool c++ "install GCC or Clang with C++17 support"
|
|
fi
|
|
check_tool git "sudo apt install git"
|
|
check_tool java "sudo apt install default-jdk"
|
|
check_tool ld.lld "install LLD"
|
|
check_tool elfedit "install binutils"
|
|
|
|
if [[ "${EXTRACT_APK}" == true ]]; then
|
|
check_tool unzip "sudo apt install unzip"
|
|
fi
|
|
if [[ "${EXTRACT_APK}" == true && -n "${APK_URL}" ]] &&
|
|
! command -v curl &>/dev/null; then
|
|
check_tool wget "sudo apt install wget"
|
|
fi
|
|
|
|
if [[ "${EXTRACT_APK}" == true && -n "${APK_URL}" ]]; then
|
|
step "2/5 downloading Roblox APK"
|
|
APK_PATH="${PROJECT_ROOT}/rbx_bin/roblox-x86_64.apk"
|
|
mkdir -p "${RBX_BIN_DIR}"
|
|
info "URL: ${APK_URL}"
|
|
info "Destination: ${APK_PATH}"
|
|
if command -v curl &>/dev/null; then
|
|
curl -L --progress-bar -o "${APK_PATH}" "${APK_URL}"
|
|
else
|
|
wget -q --show-progress -O "${APK_PATH}" "${APK_URL}"
|
|
fi
|
|
success "APK downloaded."
|
|
fi
|
|
|
|
LIBROBLOX_DST="${RBX_BIN_DIR}/libroblox.so"
|
|
|
|
if [[ -n "${ROBLOX_LIB_PATH:-}" ]]; then
|
|
info "Explicit runtime library override detected — APK extraction disabled."
|
|
EXTRACT_APK=false
|
|
EXPLICIT_RUNTIME_OVERRIDE=true
|
|
fi
|
|
|
|
if [[ "${EXTRACT_APK}" == true ]]; then
|
|
step "3/5 extracting libroblox.so"
|
|
[[ -n "${APK_PATH}" ]] || die "explicit APK extraction has no input"
|
|
[[ -f "${APK_PATH}" ]] || die "APK not found: ${APK_PATH}"
|
|
mkdir -p "${RBX_BIN_DIR}"
|
|
info "APK: ${APK_PATH}"
|
|
info "Looking for lib/x86_64/libroblox.so inside the archive…"
|
|
|
|
if ! unzip -l "${APK_PATH}" | grep -q "lib/x86_64/libroblox.so"; then
|
|
die "APK does not contain lib/x86_64/libroblox.so; use an x86_64 split APK"
|
|
else
|
|
unzip -jo "${APK_PATH}" "lib/x86_64/libroblox.so" -d "${RBX_BIN_DIR}"
|
|
success "Extracted → ${LIBROBLOX_DST}"
|
|
fi
|
|
else
|
|
step "2/5 selecting managed Roblox payload"
|
|
success "No APK or libroblox.so is required at build time."
|
|
fi
|
|
|
|
step "4/5 initialising git submodules"
|
|
cd "${PROJECT_ROOT}"
|
|
if [[ -f ".gitmodules" ]]; then
|
|
git submodule update --init --recursive
|
|
success "Submodules ready."
|
|
else
|
|
warn "No .gitmodules found — skipping submodule init."
|
|
info "To add submodules run: ./scripts/add_submodules.sh"
|
|
fi
|
|
|
|
step "5/5 configuring CMake"
|
|
|
|
if [[ "${CLEAN}" == true && -d "${BUILD_DIR}" ]]; then
|
|
info "Removing old build directory…"
|
|
rm -rf "${BUILD_DIR}"
|
|
fi
|
|
|
|
if [[ "${RUN_TESTS}" == true ]]; then
|
|
CMAKE_BUILD_TESTING=ON
|
|
else
|
|
CMAKE_BUILD_TESTING=OFF
|
|
fi
|
|
|
|
cmake_arguments=(
|
|
-S "${PROJECT_ROOT}"
|
|
-B "${BUILD_DIR}"
|
|
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}"
|
|
-DBUILD_TESTING="${CMAKE_BUILD_TESTING}"
|
|
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
|
|
)
|
|
if [[ -n "${CMAKE_TOOLCHAIN_FILE}" ]]; then
|
|
cmake_arguments+=("-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}")
|
|
fi
|
|
if [[ -n "${CMAKE_SYSROOT}" ]]; then
|
|
cmake_arguments+=("-DCMAKE_SYSROOT=${CMAKE_SYSROOT}")
|
|
fi
|
|
cmake "${cmake_arguments[@]}"
|
|
|
|
success "CMake configuration complete."
|
|
|
|
step "building Mocktail"
|
|
|
|
cmake --build "${BUILD_DIR}" -j"${JOBS}"
|
|
|
|
success "Build complete → ${BUILD_DIR}/mocktail"
|
|
|
|
if [[ "${RUN_TESTS}" == true ]]; then
|
|
step "running unit tests"
|
|
ctest --test-dir "${BUILD_DIR}" --output-on-failure -j"${JOBS}"
|
|
success "All tests passed."
|
|
fi
|
|
|
|
echo
|
|
success "Build successful."
|
|
echo "Run:"
|
|
echo -e " ${CYAN}${BUILD_DIR}/mocktail${RESET}"
|
|
if [[ "${EXPLICIT_RUNTIME_OVERRIDE}" == true ]]; then
|
|
info "The explicit runtime library override remains active for this shell."
|
|
elif [[ "${EXTRACT_APK}" == false ]]; then
|
|
info "First launch downloads, verifies, and activates the supported Roblox x86_64 payload automatically."
|
|
else
|
|
info "Explicit APK extraction completed; managed first-run updates remain available."
|
|
fi
|
|
echo
|