JJ_MKVMaker/tool/build_rhwp_android.sh

100 lines
6.1 KiB
Bash

#!/bin/sh
# 관리자 지시 (10/20): Android (arm64) 에서 HWP · HWPX 를 PDF 로 바꿔 앱의 보기 화면으로 연다 - rhwp (Rust, MIT) 를
# tool/rhwp_ffi (얇은 C ABI) 와 함께 NDK 로 빌드해 third_party/rhwp/android/arm64-v8a/libjj_rhwp.so 로 둔다 (rsync · 7zz 와 같은 방식 -
# APK 의 jniLibs 로 들어가 앱이 dart:ffi 로 읽는다).
# 소스: https://github.com/edwardkim/rhwp v0.8.7 = 커밋 1a76570 (고정 - git 커밋 해시가 내용의 SHA-1 지문이다, 고치지 않음).
# 저장소가 크므로 (예제 문서 · PDF 로 4GB 넘음) 빌드에 쓰는 폴더만 받는다 (git sparse, 깊이 1).
# 라이선스: rhwp MIT (LICENSE → third_party/rhwp) · .so 에 실제로 링크되는 crate 마다 이름 · 판 · 라이선스 · 원문은
# tool/licenses/rhwp_crates.py 가 assets/licenses/RHWP_LICENSES.txt 로 만든다 (관리자 지시 10/20 - 저장소의 THIRD_PARTY_LICENSES.md 는
# npm 쪽이 섞여 있고 링크되는 crate 가 빠져 쓰지 않는다). Cargo.lock 이 바뀌면 test/licenses_test.dart 가 다시 만들라고 잡는다.
# 도구: Rust 1.93.1 (rhwp 의 rust-toolchain.toml 과 같음, tools/rust - RUSTUP_HOME · CARGO_HOME) + Android NDK clang (링커).
# Windows 에서는 호스트 쪽 (빌드 스크립트) 을 MSVC 로 링크하므로 tools/VSBuildTools 의 vcvars64 환경을 읽어 온다.
# 16KB 쪽 기기 (Android 15+) 에서도 읽히게 -z max-page-size=16384, 다시 만들어도 같은 파일이 되게 경로를 /jj 로 바꿔 적는다.
# 의존 crate 판은 tool/rhwp_ffi/Cargo.lock 으로 고정 (--locked).
# 사용법 (Git Bash): sh tool/build_rhwp_android.sh - Android NDK 가 필요 (ANDROID_NDK 또는 tools/android-sdk/ndk/*)
# 다시 만들어지는지 보기: JJ_RHWP_CHECK=1 sh tool/build_rhwp_android.sh (깨끗한 target 으로 두 번 빌드해 해시를 견줌)
set -e
APP=$(cd "$(dirname "$0")/.." && pwd)
TOOLS=$(cd "$APP/.." && pwd)/tools
VER=0.8.7
REV=1a76570e833917d15817415a53c09ad61ab3203f
NDK_ROOT=${ANDROID_NDK:-$(ls -d "$TOOLS"/android-sdk/ndk/* | sort | tail -1)}
case "$(uname -s)" in MINGW*|MSYS*|CYGWIN*) HOST=windows-x86_64; EXE=.exe; CMD=.cmd ;; Darwin) HOST=darwin-x86_64; EXE=; CMD= ;; *) HOST=linux-x86_64; EXE=; CMD= ;; esac
TC=$NDK_ROOT/toolchains/llvm/prebuilt/$HOST/bin
export RUSTUP_HOME=${RUSTUP_HOME:-$TOOLS/rust/rustup}
export CARGO_HOME=${CARGO_HOME:-$TOOLS/rust/cargo}
export PATH="$CARGO_HOME/bin:$PATH"
# Windows: 호스트 링커 (MSVC) 환경
if [ "$HOST" = windows-x86_64 ] && [ -z "$VCINSTALLDIR" ]; then
VC=$(cygpath -w "$TOOLS/VSBuildTools/VC/Auxiliary/Build/vcvars64.bat")
ENVF=$(mktemp)
# cmd 에 따옴표를 넘기면 Git Bash 가 바꿔 버려, 부를 것을 .cmd 파일로 적어 그것을 돌린다
BAT=$(mktemp --suffix=.cmd)
printf '@call "%s" >nul\r\n@set\r\n' "$VC" > "$BAT"
cmd //c "$(cygpath -w "$BAT")" | tr -d '\r' > "$ENVF"
rm -f "$BAT"
while IFS='=' read -r k v; do
case "$k" in
Path|PATH) PATH="$(cygpath -u -p "$v"):$PATH" ;;
LIB|LIBPATH|INCLUDE|VCINSTALLDIR|VCToolsInstallDir|WindowsSdkDir|WindowsSDKVersion|UCRTVersion|UniversalCRTSdkDir) export "$k=$v" ;;
esac
done < "$ENVF"
rm -f "$ENVF"
export PATH
[ -n "$VCINSTALLDIR" ] || { echo "vcvars64 환경을 읽지 못함: $VC"; exit 1; }
fi
# 작업 폴더: tools 아래 (빌드 캐시가 수 GB - 시스템 임시 폴더 (C:) 가 모자라 시험이 실패했다, 10/20). 다시 빌드할 때 이어 쓴다
WORK=${JJ_RHWP_WORK:-$TOOLS/src/rhwp/build}
mkdir -p "$WORK"
SRC=$WORK/rhwp
if [ "$(git -C "$SRC" rev-parse HEAD 2>/dev/null)" != "$REV" ]; then
rm -rf "$SRC"
git init -q "$SRC"
git -C "$SRC" remote add origin https://github.com/edwardkim/rhwp.git
git -C "$SRC" sparse-checkout init --no-cone
printf '%s\n' '/*' '!/samples/' '!/pdf/' '!/mydocs/' '!/saved/' '!/tests/' '!/gym/' '!/rhwp-*/' '!/npm/' '!/typescript/' \
'!/tools/' '!/fuzz/' '!/scripts/' '/saved/blank2010.hwp' '/mydocs/manual/' '/mydocs/tech/' > "$SRC/.git/info/sparse-checkout"
git -C "$SRC" fetch -q --depth 1 --filter=blob:none origin "$REV"
git -C "$SRC" checkout -q FETCH_HEAD
fi
[ "$(git -C "$SRC" rev-parse HEAD)" = "$REV" ] || { echo "rhwp 커밋이 다름"; exit 1; }
[ -z "$(git -C "$SRC" status --porcelain)" ] || { echo "rhwp 소스가 바뀌어 있음"; exit 1; }
rm -rf "$WORK/ffi"
cp -r "$APP/tool/rhwp_ffi" "$WORK/ffi"
# 처음 한 번: 의존 판을 rhwp 의 Cargo.lock 그대로 이어받아 tool/rhwp_ffi/Cargo.lock 을 만든다 (그 뒤로는 --locked)
LOCKED=--locked
if [ ! -f "$APP/tool/rhwp_ffi/Cargo.lock" ]; then
cp "$SRC/Cargo.lock" "$WORK/ffi/Cargo.lock"
LOCKED=
fi
export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER="$TC/aarch64-linux-android24-clang$CMD"
export CC_aarch64_linux_android="$TC/aarch64-linux-android24-clang$CMD"
export AR_aarch64_linux_android="$TC/llvm-ar$EXE"
W=$WORK
[ "$HOST" = windows-x86_64 ] && W=$(cygpath -m "$WORK")
export RUSTFLAGS="-C link-arg=-Wl,-z,max-page-size=16384 -C link-arg=-Wl,--build-id=none --remap-path-prefix=$W=/jj --remap-path-prefix=$(cygpath -m "$CARGO_HOME" 2>/dev/null || echo "$CARGO_HOME")=/cargo"
export JJ_RHWP_VERSION=$VER
build() {
cargo build -q --release $LOCKED --target aarch64-linux-android --manifest-path "$WORK/ffi/Cargo.toml" --target-dir "$1"
"$TC/llvm-strip$EXE" -o "$2" "$1/aarch64-linux-android/release/libjj_rhwp.so"
}
OUT="$APP/third_party/rhwp/android/arm64-v8a"
mkdir -p "$OUT"
build "$WORK/target" "$OUT/libjj_rhwp.so"
[ -n "$LOCKED" ] || cp "$WORK/ffi/Cargo.lock" "$APP/tool/rhwp_ffi/Cargo.lock"
cp "$SRC/LICENSE" "$OUT/../LICENSE.txt"
rm -f "$OUT/../THIRD_PARTY_LICENSES.md"
# 링크되는 crate 의 라이선스 · 원문 (cargo tree · metadata - 의존은 위 빌드가 받아 둠)
python "$APP/tool/licenses/rhwp_crates.py" "$WORK/ffi/Cargo.toml" "$SRC" "$VER" "$REV" "$APP/assets/licenses/RHWP_LICENSES.txt"
if [ -n "$JJ_RHWP_CHECK" ]; then
rm -rf "$WORK/target2"
build "$WORK/target2" "$WORK/again.so"
A=$(sha256sum < "$OUT/libjj_rhwp.so"); B=$(sha256sum < "$WORK/again.so")
[ "$A" = "$B" ] && echo "다시 만들어도 같음" || { echo "다시 만들면 다름: $A / $B"; exit 1; }
fi
ls -l "$OUT/libjj_rhwp.so"
sha256sum "$OUT/libjj_rhwp.so"