From 48ca0eb5d3db423e73a893896e4b95e619921cb2 Mon Sep 17 00:00:00 2001 From: Moustapha Kodjo Amadou <107993382+kodjodevf@users.noreply.github.com> Date: Mon, 14 Jul 2025 14:54:33 +0100 Subject: [PATCH] add go build script --- go/build_go.sh | 362 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100755 go/build_go.sh diff --git a/go/build_go.sh b/go/build_go.sh new file mode 100755 index 00000000..8313a3de --- /dev/null +++ b/go/build_go.sh @@ -0,0 +1,362 @@ +#!/bin/bash + +# Go build script for Mangayomi +# It supports Linux, macOS, Windows, Android, and iOS builds. +# to build, run: +# ./build_go.sh [linux|macos|windows|android|ios] [--all] + +set -e # Stop on error + +# Colors for messages +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Colored message functions +log_info() { + echo -e "${BLUE}[INFO]${NC} $1" +} + +log_success() { + echo -e "${GREEN}[SUCCESS]${NC} $1" +} + +log_warning() { + echo -e "${YELLOW}[WARNING]${NC} $1" +} + +log_error() { + echo -e "${RED}[ERROR]${NC} $1" +} + +# Check prerequisites +check_prerequisites() { + log_info "Checking prerequisites..." + + # Check Go + if ! command -v go &> /dev/null; then + log_error "Go is not installed. Please install Go 1.22 or newer." + exit 1 + fi + + GO_VERSION=$(go version | grep -o 'go[0-9]\+\.[0-9]\+' | sed 's/go//') + log_info "Detected Go version: $GO_VERSION" + + # Check if we're in the go directory + if [ ! -f "go.mod" ]; then + log_error "go.mod not found. Run this script from the 'go' directory of the Mangayomi project." + exit 1 + fi +} + +# Build for Linux +build_linux() { + log_info "Building for Linux..." + mkdir -p ../linux/bundle/lib + go build -buildmode=c-shared -ldflags="-s -w" -trimpath -o ../linux/bundle/lib/libmtorrentserver.so ./binding/desktop + log_success "Linux build completed: ../linux/bundle/lib/libmtorrentserver.so" +} + +# Build for macOS +build_macos() { + log_info "Building for macOS..." + + if [[ "$OSTYPE" != "darwin"* ]]; then + log_warning "macOS build requested but you're not on macOS. Build might fail." + fi + + mkdir -p ../macos/Frameworks + + # Build ARM64 + log_info "Building macOS ARM64..." + CGO_ENABLED=1 GOARCH=arm64 go build -buildmode=c-shared -ldflags="-s -w" -trimpath -o libmtorrentserver_arm64.dylib ./binding/desktop + + # Build AMD64 + log_info "Building macOS AMD64..." + CGO_ENABLED=1 GOARCH=amd64 go build -buildmode=c-shared -ldflags="-s -w" -trimpath -o libmtorrentserver_amd64.dylib ./binding/desktop + + # Create universal binary + if command -v lipo &> /dev/null; then + log_info "Creating universal binary..." + lipo -create -output ../macos/Frameworks/libmtorrentserver.dylib libmtorrentserver_arm64.dylib libmtorrentserver_amd64.dylib + + # Clean up intermediate binaries + log_info "Cleaning up intermediate binaries..." + rm -f libmtorrentserver_arm64.dylib libmtorrentserver_amd64.dylib + rm -f libmtorrentserver_arm64.h libmtorrentserver_amd64.h + + log_success "macOS build completed: ../macos/Frameworks/libmtorrentserver.dylib (universal)" + else + log_warning "lipo not available. Separate binaries are available." + fi +} + +# Build for Windows +build_windows() { + log_info "Building for Windows..." + + mkdir -p ../windows + + # Configure environment for Windows + export CGO_ENABLED=1 + export CC=gcc + export GOARCH=amd64 + + if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "win32" ]]; then + # Native Windows + go build -buildmode=c-shared -ldflags="-s -w -extldflags=-static" -trimpath -o ../windows/libmtorrentserver.dll ./binding/desktop + else + # Cross-compilation from Unix + if command -v x86_64-w64-mingw32-gcc &> /dev/null; then + export CC=x86_64-w64-mingw32-gcc + export GOOS=windows + go build -buildmode=c-shared -ldflags="-s -w -extldflags=-static" -trimpath -o ../windows/libmtorrentserver.dll ./binding/desktop + else + log_error "Windows cross-compiler not found. Install mingw-w64." + return 1 + fi + fi + + log_success "Windows build completed: ../windows/libmtorrentserver.dll" +} + +# Build for Android +build_android() { + log_info "Building for Android..." + + # Check gomobile + if ! command -v gomobile &> /dev/null; then + log_info "Installing gomobile..." + go install golang.org/x/mobile/cmd/gomobile@latest + go install golang.org/x/mobile/cmd/gobind@latest + + # Add GOPATH/bin to PATH if necessary + export PATH=$PATH:$(go env GOPATH)/bin + + # Initialize gomobile + log_info "Initializing gomobile..." + gomobile init -v + fi + + # Check Android NDK + if [ -z "$ANDROID_NDK_HOME" ] && [ -z "$ANDROID_NDK_ROOT" ]; then + log_warning "ANDROID_NDK_HOME or ANDROID_NDK_ROOT not defined. Android build might fail." + log_warning "Install Android Studio and NDK, then set the environment variable." + log_warning "Example: export ANDROID_NDK_HOME=/path/to/android/sdk/ndk/25.2.9519653" + fi + + # Check Java JDK + if ! javac -version &> /dev/null; then + log_warning "javac (Java Development Kit) not working. Android build might fail." + log_warning "Install Oracle JDK or OpenJDK and configure JAVA_HOME." + log_warning "On macOS: brew install openjdk@11" + log_warning "Then: export JAVA_HOME=\$(brew --prefix openjdk@11)" + fi + + go get -u golang.org/x/mobile + + log_info "Building Android AAR..." + + mkdir -p ../android/app/libs + + # Try Android build with enhanced error handling + # Uses -checklinkname=0 and -tags to allow anet v0.0.5 usage (solution inspired by Gopeed) + if ! gomobile bind -v -tags mobile -target=android/arm,android/arm64,android/amd64,android/386 -androidapi 21 -ldflags="-s -w -checklinkname=0" -trimpath -o ../android/app/libs/libmtorrentserver.aar ./binding/mobile; then + log_error "Android build failed." + log_error "Common error: 'invalid reference to net.zoneCache'" + log_error "" + log_error "Possible solutions:" + log_error "1. Install and configure Android NDK correctly:" + log_error " - Download Android Studio" + log_error " - Install Android NDK via SDK Manager" + log_error " - Set ANDROID_NDK_HOME" + log_error "" + log_error "2. Update Go to latest version:" + log_error " - current go version: $(go version)" + log_error " - Recommended: Go 1.21 or newer" + log_error "" + log_error "3. Known issue with github.com/wlynxg/anet:" + log_error " - This package uses internal Go APIs" + log_error " - Applied solution: replace directive in go.mod" + log_error "" + log_error "4. Check Java JDK installation:" + log_error " - Install JDK: brew install openjdk@11" + log_error " - Set JAVA_HOME: export JAVA_HOME=\$(brew --prefix openjdk@11)" + log_error "" + log_error "5. Alternative - Desktop build only:" + log_error " ./build_go.sh linux macos windows" + + return 1 + fi + + rm -f ../android/app/libs/libmtorrentserver-sources.jar + log_success "Android build completed: ../android/app/libs/libmtorrentserver.aar" +} + + +# Build for iOS +build_ios() { + log_info "Building for iOS..." + + if [[ "$OSTYPE" != "darwin"* ]]; then + log_error "iOS build is only possible on macOS." + return 1 + fi + + # Check Xcode + if ! command -v xcodebuild &> /dev/null; then + log_error "Xcode is not installed." + return 1 + fi + + # Check gomobile + if ! command -v gomobile &> /dev/null; then + log_info "Installing gomobile..." + go install golang.org/x/mobile/cmd/gomobile@latest + go install golang.org/x/mobile/cmd/gobind@latest + + # Add GOPATH/bin to PATH if necessary + export PATH=$PATH:$(go env GOPATH)/bin + + # Initialize gomobile + log_info "Initializing gomobile..." + gomobile init -v + fi + + go get -u golang.org/x/mobile + + log_info "Building iOS XCFramework..." + + mkdir -p ../ios/Frameworks + + # Uses same optimizations as Android for anet v0.0.5 compatibility + gomobile bind -v -tags mobile -target=ios,iossimulator -ldflags="-s -w -checklinkname=0" -trimpath -o ../ios/Frameworks/libmtorrentserver.xcframework ./binding/mobile + + log_success "iOS build completed: ../ios/Frameworks/libmtorrentserver.xcframework" +} + + +# Show help +show_help() { + echo "Usage: $0 [OPTIONS] [TARGETS]" + echo "" + echo "OPTIONS:" + echo " -h, --help Show this help" + echo " -a, --all Build for all supported platforms" + echo "" + echo "TARGETS:" + echo " linux Build for Linux" + echo " macos Build for macOS" + echo " windows Build for Windows" + echo " android Build for Android" + echo " ios Build for iOS" + echo "" + echo "Examples:" + echo " $0 linux macos # Build for Linux and macOS" +} + +# Variables +BUILD_ALL=false +TARGETS=() + +# Parser les arguments +while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + show_help + exit 0 + ;; + -a|--all) + BUILD_ALL=true + shift + ;; + linux|macos|windows|android|ios) + TARGETS+=("$1") + shift + ;; + *) + log_error "Unknown option: $1" + show_help + exit 1 + ;; + esac +done + +# Main +main() { + log_info "Starting Go build for Mangayomi" + + check_prerequisites + + if [ "$BUILD_ALL" = true ]; then + TARGETS=("linux" "macos" "windows" "android" "ios") + fi + + if [ ${#TARGETS[@]} -eq 0 ]; then + log_warning "No target specified. Building for current platform..." + case "$OSTYPE" in + linux*) TARGETS=("linux") ;; + darwin*) TARGETS=("macos") ;; + msys*|win32*) TARGETS=("windows") ;; + *) + log_error "Unsupported platform: $OSTYPE" + show_help + exit 1 + ;; + esac + fi + + # Build for each target + for target in "${TARGETS[@]}"; do + log_info "--- Building for: $target ---" + case $target in + linux) + if build_linux; then + log_success "✅ Build $target successful" + else + log_error "❌ Build $target failed" + fi + ;; + macos) + if build_macos; then + log_success "✅ Build $target successful" + else + log_error "❌ Build $target failed" + fi + ;; + windows) + if build_windows; then + log_success "✅ Build $target successful" + else + log_error "❌ Build $target failed" + fi + ;; + android) + if build_android; then + log_success "✅ Build $target successful" + else + log_error "❌ Build $target failed" + log_warning "Android build may fail due to compatibility issues" + log_warning "Other platforms should work normally" + fi + ;; + ios) + if build_ios; then + log_success "✅ Build $target successful" + else + log_error "❌ Build $target failed" + fi + ;; + *) + log_error "Unknown target: $target" + ;; + esac + echo "" # Empty line for readability + done + +} + +# Execute main script +main "$@"