2 changed files with 284 additions and 1 deletions
@ -0,0 +1,284 @@
|
||||
#!/bin/bash |
||||
# cross-build-win.sh — кросс-компиляция uTun для Windows 10 из Linux |
||||
# Использование: ./cross-build-win.sh [--clean] |
||||
set -euo pipefail |
||||
|
||||
RED='\033[0;31m' |
||||
GREEN='\033[0;32m' |
||||
YELLOW='\033[1;33m' |
||||
CYAN='\033[0;36m' |
||||
NC='\033[0m' |
||||
|
||||
step() { echo -e "${CYAN}===${NC} $*"; } |
||||
ok() { echo -e "${GREEN}[OK]${NC} $*"; } |
||||
warn() { echo -e "${YELLOW}[WARNING]${NC} $*"; } |
||||
fatal() { echo -e "${RED}FATAL:${NC} $*" >&2; exit 1; } |
||||
|
||||
trap 'fatal "script failed at line $LINENO (exit code: $?)"' ERR |
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
||||
BUILD_DIR="$SCRIPT_DIR/build-win" |
||||
PREFIX="$BUILD_DIR/prefix" |
||||
|
||||
MINGW_CC="x86_64-w64-mingw32-gcc" |
||||
MINGW_AR="x86_64-w64-mingw32-ar" |
||||
MINGW_RANLIB="x86_64-w64-mingw32-ranlib" |
||||
|
||||
MINGW_PKGS="gcc-mingw-w64-x86-64-posix g++-mingw-w64-x86-64-posix" |
||||
OPENSSL_VER="3.0.16" |
||||
OPENSSL_URL="https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_VER}/openssl-${OPENSSL_VER}.tar.gz" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 0. Аргументы |
||||
# ------------------------------------------------------------------- |
||||
CLEAN=0 |
||||
while [[ $# -gt 0 ]]; do |
||||
case "$1" in |
||||
--clean) CLEAN=1; shift ;; |
||||
*) fatal "unknown option: $1" ;; |
||||
esac |
||||
done |
||||
|
||||
if [ "$CLEAN" -eq 1 ]; then |
||||
echo -e "${YELLOW}Cleaning build directory: $BUILD_DIR${NC}" |
||||
rm -rf "$BUILD_DIR" |
||||
fi |
||||
|
||||
echo -e "${CYAN}==============================================${NC}" |
||||
echo -e "${CYAN} uTun Cross-Compilation for Windows 10${NC}" |
||||
echo -e "${CYAN}==============================================${NC}" |
||||
echo "" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 1. Проверка системы |
||||
# ------------------------------------------------------------------- |
||||
step "Checking system..." |
||||
if [ "$(uname -s)" != "Linux" ]; then |
||||
fatal "This script only runs on Linux. Detected: $(uname -s)" |
||||
fi |
||||
if [ "$(uname -m)" != "x86_64" ]; then |
||||
fatal "This script requires x86_64 architecture. Detected: $(uname -m)" |
||||
fi |
||||
|
||||
if ! command -v apt-get &>/dev/null; then |
||||
fatal "apt-get not found. Only Debian/Ubuntu are supported." |
||||
fi |
||||
ok "System: Linux x86_64 with apt" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 2. Установка пакетов |
||||
# ------------------------------------------------------------------- |
||||
step "Installing required packages..." |
||||
|
||||
need_install=() |
||||
for pkg in $MINGW_PKGS; do |
||||
if ! dpkg -s "$pkg" &>/dev/null 2>&1; then |
||||
need_install+=("$pkg") |
||||
fi |
||||
done |
||||
if ! command -v wget &>/dev/null && ! command -v curl &>/dev/null; then |
||||
need_install+=("wget") |
||||
fi |
||||
|
||||
if [ ${#need_install[@]} -gt 0 ]; then |
||||
echo " Installing: ${need_install[*]}" |
||||
sudo apt-get update -qq || fatal "apt-get update failed" |
||||
sudo apt-get install -y -qq "${need_install[@]}" || fatal "apt-get install failed" |
||||
ok "Packages installed: ${need_install[*]}" |
||||
else |
||||
ok "All packages already installed" |
||||
fi |
||||
|
||||
# Проверка компилятора |
||||
for tool in "$MINGW_CC" "$MINGW_AR" "$MINGW_RANLIB"; do |
||||
if ! command -v "$tool" &>/dev/null; then |
||||
fatal "$tool not found after package installation" |
||||
fi |
||||
done |
||||
ok "Cross-compiler: $($MINGW_CC --version | head -1)" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 3. Кросс-компиляция OpenSSL |
||||
# ------------------------------------------------------------------- |
||||
OPENSSL_SRC="$BUILD_DIR/openssl-${OPENSSL_VER}" |
||||
LIBCRYPTO="$PREFIX/lib/libcrypto.a" |
||||
|
||||
if [ -f "$LIBCRYPTO" ]; then |
||||
ok "OpenSSL already built: $LIBCRYPTO" |
||||
else |
||||
step "Building OpenSSL ${OPENSSL_VER} for Windows..." |
||||
|
||||
mkdir -p "$BUILD_DIR" |
||||
|
||||
TARBALL="$BUILD_DIR/openssl-${OPENSSL_VER}.tar.gz" |
||||
if [ ! -f "$TARBALL" ]; then |
||||
echo " Downloading OpenSSL ${OPENSSL_VER}..." |
||||
if command -v wget &>/dev/null; then |
||||
wget -q --show-progress -O "$TARBALL" "$OPENSSL_URL" || fatal "wget download failed for $OPENSSL_URL" |
||||
else |
||||
curl -L --progress-bar -o "$TARBALL" "$OPENSSL_URL" || fatal "curl download failed for $OPENSSL_URL" |
||||
fi |
||||
ok "Downloaded: $TARBALL" |
||||
fi |
||||
|
||||
if [ ! -d "$OPENSSL_SRC" ]; then |
||||
echo " Extracting..." |
||||
tar xzf "$TARBALL" -C "$BUILD_DIR" || fatal "tar extract failed" |
||||
fi |
||||
|
||||
echo " Configuring OpenSSL for mingw64..." |
||||
cd "$OPENSSL_SRC" |
||||
./Configure --cross-compile-prefix=x86_64-w64-mingw32- \ |
||||
mingw64 no-shared no-tests \ |
||||
--prefix="$PREFIX" --libdir="$PREFIX/lib" --openssldir="$PREFIX/ssl" \ |
||||
|| fatal "OpenSSL configure failed (see output above)" |
||||
ok "OpenSSL configured" |
||||
|
||||
echo " Compiling OpenSSL..." |
||||
make -j"$(nproc)" || fatal "OpenSSL make failed" |
||||
echo " Installing OpenSSL..." |
||||
make install_sw >/dev/null || fatal "OpenSSL make install_sw failed" |
||||
cd "$SCRIPT_DIR" |
||||
|
||||
# OpenSSL может установить в lib64/ вместо lib/ — поправим |
||||
if [ ! -f "$LIBCRYPTO" ] && [ -f "$PREFIX/lib64/libcrypto.a" ]; then |
||||
ln -sf lib64 "$PREFIX/lib" 2>/dev/null || cp -r "$PREFIX/lib64" "$PREFIX/lib" 2>/dev/null || true |
||||
fi |
||||
if [ ! -f "$LIBCRYPTO" ]; then |
||||
fatal "libcrypto.a was not found at $PREFIX/lib/ or $PREFIX/lib64/" |
||||
fi |
||||
ok "OpenSSL built: $LIBCRYPTO" |
||||
fi |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 4. Сборка libuasync.a |
||||
# ------------------------------------------------------------------- |
||||
step "Building libuasync.a..." |
||||
|
||||
LIB_OBJDIR="$BUILD_DIR/lib-objs" |
||||
mkdir -p "$LIB_OBJDIR" |
||||
|
||||
# Все .c файлы из lib/Makefile.am + myip.c (реализация get_my_ip) |
||||
LIB_SOURCES=( |
||||
u_async.c ll_queue.c memory_pool.c debug_config.c timeout_heap.c |
||||
sha256.c mem.c serialize.c swm_min.c getmyip.c radix.c tcp_io.c |
||||
myip.c platform_compat.c socket_compat.c |
||||
liblmdb/mdb.c liblmdb/midl.c |
||||
) |
||||
|
||||
LIB_CFLAGS="-D_ISOC99_SOURCE -DDEBUG_OUTPUT_STDERR -DUSE_OPENSSL" |
||||
LIB_CFLAGS+=" -I$SCRIPT_DIR/lib -I$SCRIPT_DIR/src -I$SCRIPT_DIR/lib/liblmdb" |
||||
LIB_CFLAGS+=" -I$PREFIX/include" |
||||
LIB_CFLAGS+=" -g -O2 -Wno-deprecated-declarations" |
||||
|
||||
for src in "${LIB_SOURCES[@]}"; do |
||||
obj="$LIB_OBJDIR/$(basename "${src%.c}.o")" |
||||
echo " CC lib/$src" |
||||
"$MINGW_CC" $LIB_CFLAGS -c "$SCRIPT_DIR/lib/$src" -o "$obj" \ |
||||
|| fatal "compilation failed: lib/$src" |
||||
done |
||||
|
||||
"$MINGW_AR" crs "$BUILD_DIR/libuasync.a" "$LIB_OBJDIR"/*.o \ |
||||
|| fatal "ar failed for libuasync.a" |
||||
"$MINGW_RANLIB" "$BUILD_DIR/libuasync.a" 2>/dev/null || true |
||||
ok "libuasync.a ($(wc -c < "$BUILD_DIR/libuasync.a") bytes)" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 5. Сборка объектных файлов для utun.exe |
||||
# ------------------------------------------------------------------- |
||||
step "Compiling utun source files..." |
||||
|
||||
SRC_OBJDIR="$BUILD_DIR/src-objs" |
||||
mkdir -p "$SRC_OBJDIR" |
||||
|
||||
# Все .c файлы из src/Makefile.am (utun_CORE_SOURCES) |
||||
SRC_SOURCES=( |
||||
utun.c utun_instance.c config_parser.c config_updater.c |
||||
route_lib.c route6_lib.c route_bgp.c route_ping.c |
||||
route_node.c route_node_lmdb.c route_connectivity.c conn_mgr.c |
||||
routing.c tun_if.c tun_route.c tun_linux.c tun_freebsd.c tun_windows.c |
||||
etcp.c etcp_connections.c etcp_bbr.c etcp_loadbalancer.c |
||||
etcp_debug.c etcp_dump.c secure_channel.c crc32.c |
||||
stcp_link.c stcp.c stcp_server.c stcp_client.c |
||||
pkt_normalizer.c packet_dump.c etcp_api.c |
||||
control_server.c msg_transport.c |
||||
firewall.c eim_nat.c nat_transport.c dummynet.c |
||||
etcp_router.c |
||||
proxy/udp_proxy.c proxy/socks_proxy.c |
||||
lwip_tcp/lwip_pbuf.c |
||||
) |
||||
|
||||
SRC_CFLAGS="-DUSE_OPENSSL" |
||||
SRC_CFLAGS+=" -I$SCRIPT_DIR/src -I$SCRIPT_DIR/lib -I$SCRIPT_DIR/lib/liblmdb" |
||||
SRC_CFLAGS+=" -I$SCRIPT_DIR/tinycrypt/lib/include -I$SCRIPT_DIR/tinycrypt/lib/source" |
||||
SRC_CFLAGS+=" -I$PREFIX/include" |
||||
SRC_CFLAGS+=" -g -O2 -Wno-deprecated-declarations" |
||||
|
||||
TOTAL=${#SRC_SOURCES[@]} |
||||
CURRENT=0 |
||||
FAILED=() |
||||
|
||||
for src in "${SRC_SOURCES[@]}"; do |
||||
CURRENT=$((CURRENT + 1)) |
||||
# Имя объектного файла: заменяем / на _ (для proxy/ и lwip_tcp/) |
||||
obj_name="$(echo "$src" | tr '/' '_')" |
||||
obj="$SRC_OBJDIR/${obj_name%.c}.o" |
||||
printf " [%3d/%3d] CC src/%s\n" "$CURRENT" "$TOTAL" "$src" |
||||
if ! "$MINGW_CC" $SRC_CFLAGS -c "$SCRIPT_DIR/src/$src" -o "$obj" 2>&1; then |
||||
FAILED+=("src/$src") |
||||
fi |
||||
done |
||||
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then |
||||
echo "" |
||||
fatal "compilation failed for: ${FAILED[*]}" |
||||
fi |
||||
ok "All $TOTAL source files compiled" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 6. Линковка utun.exe |
||||
# ------------------------------------------------------------------- |
||||
step "Linking utun.exe..." |
||||
|
||||
"$MINGW_CC" -o "$SCRIPT_DIR/utun.exe" \ |
||||
"$SRC_OBJDIR"/*.o \ |
||||
"$BUILD_DIR/libuasync.a" \ |
||||
"$LIBCRYPTO" \ |
||||
-lws2_32 -liphlpapi -ladvapi32 -lbcrypt -lcrypt32 -lpthread -lm \ |
||||
-static \ |
||||
|| fatal "linking failed (see undefined references above)" |
||||
|
||||
ok "utun.exe ($(wc -c < "$SCRIPT_DIR/utun.exe") bytes)" |
||||
|
||||
# ------------------------------------------------------------------- |
||||
# 7. Копирование wintun.dll и финал |
||||
# ------------------------------------------------------------------- |
||||
echo "" |
||||
if [ -f "$SCRIPT_DIR/lib/wintun.dll" ]; then |
||||
cp "$SCRIPT_DIR/lib/wintun.dll" "$SCRIPT_DIR/" |
||||
ok "wintun.dll copied to project root" |
||||
else |
||||
warn "wintun.dll not found in lib/ — place it manually alongside utun.exe" |
||||
fi |
||||
|
||||
echo "" |
||||
echo -e "${GREEN}==============================================${NC}" |
||||
echo -e "${GREEN} Build successful!${NC}" |
||||
echo -e "${GREEN} Binary: utun.exe${NC}" |
||||
echo -e "${GREEN}==============================================${NC}" |
||||
echo "" |
||||
|
||||
if [ -f "$SCRIPT_DIR/lib/wintun.dll" ]; then |
||||
echo "Run on Windows:" |
||||
echo " 1. Install Wintun driver (https://www.wintun.net)" |
||||
echo " 2. Copy utun.exe + wintun.dll to the same directory" |
||||
echo " 3. Run: utun.exe -f -p utun.pid -l utun.log" |
||||
else |
||||
echo "Run on Windows:" |
||||
echo " 1. Install Wintun driver (https://www.wintun.net)" |
||||
echo " 2. Copy utun.exe + wintun.dll to the same directory" |
||||
echo " 3. Run: utun.exe -f -p utun.pid -l utun.log" |
||||
fi |
||||
echo "" |
||||
|
||||
exit 0 |
||||
Loading…
Reference in new issue