#!/bin/bash
# compile.sh — KL630 cross-compile (ARM armv7-a)
# Run inside Docker: docker run --rm -v "<host_path>:/workspace/kl630_build" kl630-dev bash /workspace/kl630_build/compile.sh
set -e

WORKSPACE=/workspace/kl630_build
BUILD_DIR=$WORKSPACE/build
OUTPUT=$BUILD_DIR/kp_firmware_host_stream
CC=arm-linux-gnueabihf-gcc
LIB_DIR=$WORKSPACE/lib

echo "=== Checking compiler ==="
which $CC || { echo "ERROR: $CC not found"; exit 1; }
$CC --version | head -1

mkdir -p $BUILD_DIR

CFLAGS="-DVATICS_PLATFORM -DKL630 -D_GNU_SOURCE -U_FORTIFY_SOURCE"
CFLAGS="$CFLAGS -march=armv7-a -mfpu=neon -mfloat-abi=hard -Os"
CFLAGS="$CFLAGS -Wall -Wno-unused-variable -Wno-unused-function"
#CFLAGS="$CFLAGS -DENABLE_DBG_LOG"

INCLUDES="-I$WORKSPACE/include/host_stream"
INCLUDES="$INCLUDES -I$WORKSPACE/include/app_flow"
INCLUDES="$INCLUDES -I$WORKSPACE/include/app_flow/pre_post_proc"
INCLUDES="$INCLUDES -I$WORKSPACE/include/common"

# Prefer real SDK headers when available; fallback to local fake headers.
SDK_INCLUDE_CANDIDATES=(
    #"$WORKSPACE/SDK/sdk/vtcs_root_vienna/include"
	"$WORKSPACE/include/vtcs_root_vienna/include"
    "$WORKSPACE/third_party/kl630_sdk/include"
)
SDK_SYSROOT_INCLUDE="$WORKSPACE/third_party/kl630_sdk/sysroot/usr/include"
#SDK_MODULES_ROOT="$WORKSPACE/SDK/sdk/modules"
SDK_MODULES_ROOT="$WORKSPACE/include/modules"
USE_FAKE_HEADERS=1
for SDK_INCLUDE_ROOT in "${SDK_INCLUDE_CANDIDATES[@]}"; do
    if [ -d "$SDK_INCLUDE_ROOT" ]; then
        INCLUDES="$INCLUDES -I$SDK_INCLUDE_ROOT"
        if [ -d "$SDK_INCLUDE_ROOT/vmf" ]; then
            INCLUDES="$INCLUDES -I$SDK_INCLUDE_ROOT/vmf"
        fi
        USE_FAKE_HEADERS=0
        echo "=== Using SDK include: $SDK_INCLUDE_ROOT ==="
        break
    fi
done
if [ -d "$SDK_MODULES_ROOT" ]; then
    INCLUDES="$INCLUDES -I$SDK_MODULES_ROOT"
fi
if [ -d "$SDK_SYSROOT_INCLUDE" ]; then
    INCLUDES="$INCLUDES -I$SDK_SYSROOT_INCLUDE"
fi
if [ -d "$WORKSPACE/include/fake" ]; then
    # Keep fake headers as the last fallback for components not shipped in this SDK pack.
    INCLUDES="$INCLUDES -I$WORKSPACE/include/fake"
fi
if [ "$USE_FAKE_HEADERS" -eq 1 ]; then
    echo "=== Header mode: fallback fake headers ==="
else
    CFLAGS="$CFLAGS -DUSE_REAL_SDK_HEADERS=1"
    echo "=== Header mode: real SDK headers + fake fallback ==="
fi

ALL_SRCS=$(ls \
    $WORKSPACE/src/host_stream/*.c \
    $WORKSPACE/src/app_flow/*.c \
    $WORKSPACE/src/pre_post_proc/*.c \    
    2>/dev/null)

echo ""
echo "=== Source files ==="
for s in $ALL_SRCS; do echo "  $s"; done

echo ""
echo "=== Compiling ==="
OBJ_FILES=()
COMPILE_ERRORS=0

for src in $ALL_SRCS; do
    base=$(basename $src .c)
    obj=$BUILD_DIR/${base}.o
    echo "  CC  $base.c"
    if $CC $CFLAGS $INCLUDES -c "$src" -o "$obj" 2>&1; then
        OBJ_FILES+=("$obj")
    else
        echo "  *** COMPILE ERROR: $src ***"
        COMPILE_ERRORS=$((COMPILE_ERRORS + 1))
    fi
done

if [ $COMPILE_ERRORS -gt 0 ]; then
    echo ""
    echo "ERROR: $COMPILE_ERRORS file(s) failed to compile."
    exit 1
fi

echo ""
echo "=== All objects compiled ==="

# 建立 app_yolo symlink（versioned .so）
if [ ! -e "$LIB_DIR/libapp_yolo.so" ]; then
    AYSO=$(ls $LIB_DIR/libapp_yolo.so* 2>/dev/null | head -1)
    if [ -n "$AYSO" ]; then
        ln -sf $(basename $AYSO) $LIB_DIR/libapp_yolo.so
        echo "  symlink: libapp_yolo.so -> $(basename $AYSO)"
    fi
fi

# 建立 uClibc rpath-link symlinks
# 只建 libc.so.0/libc.so.1 供 rpath-link 解析 libvmf.so 的依賴
# 不建 libc.so 和 libpthread.so — 讓 -lc/-lpthread 繼續用 glibc startup
if [ -e "$LIB_DIR/libuClibc-1.0.34.so" ]; then
    for name in libc.so.0 libc.so.1; do
        [ ! -e "$LIB_DIR/$name" ] && ln -sf libuClibc-1.0.34.so $LIB_DIR/$name && echo "  symlink: $name -> libuClibc-1.0.34.so"
    done
else
    echo "WARNING: libuClibc-1.0.34.so not found in $LIB_DIR"
    echo "  Transfer it from device: tftp -p -l /lib/libuClibc-1.0.34.so -r libuClibc-1.0.34.so <host_ip> 9069"
fi

echo ""
echo "=== Linking ==="

$CC -march=armv7-a -mfpu=neon -mfloat-abi=hard \
    "${OBJ_FILES[@]}" \
    -L$LIB_DIR \
    -Wl,-rpath-link,$LIB_DIR \
    -Wl,-rpath,\$ORIGIN/lib \
    -Wl,--dynamic-linker,/lib/ld-uClibc.so.1 \
    -Wl,--allow-shlib-undefined \
    -Wl,--allow-multiple-definition \
    -lvmf -lmembroker -lmsgbroker -lsyncringbuffer -liniparser \
    -lvmf_nnm -lkutils -laio -lpthread -lm \
    -lapp_yolo \
    -o $OUTPUT \
    && echo "" \
    && echo "=== SUCCESS: $OUTPUT ===" \
    || { echo ""; echo "=== LINK FAILED ==="; exit 1; }

ls -lh $OUTPUT

echo ""
echo "=== Patching ELF for uClibc ==="
# Remove glibc dynamic linker (causes ld-uClibc to try loading itself as .so)
patchelf --remove-needed ld-linux-armhf.so.3 $OUTPUT
# Map glibc sonames to uClibc equivalents
patchelf --replace-needed libc.so.6     libc.so.0 $OUTPUT
patchelf --remove-needed libm.so.6               $OUTPUT
patchelf --remove-needed libpthread.so.0         $OUTPUT

echo "=== NEEDED after patch ==="
readelf -d $OUTPUT | grep NEEDED
