diff --git a/CMakeLists.txt b/CMakeLists.txt index 88ffc50c45..c08a59ebd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1499,78 +1499,81 @@ elseif(WIN32) set(TargetBin PPSSPPWindows) elseif(LIBRETRO) else() - if(GOLD) - set(TargetBin PPSSPPGold) - else() - set(TargetBin PPSSPPSDL) - endif() - # Require SDL - add_compile_definitions(SDL) - list(APPEND nativeExtra - SDL/SDLJoystick.h - SDL/SDLJoystick.cpp - SDL/SDLMain.cpp - SDL/SDLGLGraphicsContext.cpp - ) - if(NOT USE_LIBNX) - list(APPEND nativeExtra - SDL/SDLVulkanGraphicsContext.cpp - ) - endif() - if(SDL2_ttf_FOUND OR - (SDL2_ttf_PKGCONFIG_FOUND AND - SDL2_ttf_PKGCONFIG_VERSION VERSION_GREATER_EQUAL "2.0.18")) - add_compile_definitions(USE_SDL2_TTF) - if(FONTCONFIG_FOUND) - add_compile_definitions(USE_SDL2_TTF_FONTCONFIG) - list(APPEND nativeExtraLibs Fontconfig::Fontconfig) + if(SDL2_FOUND OR SDL2Fwk) + if(GOLD) + set(TargetBin PPSSPPGold) + else() + set(TargetBin PPSSPPSDL) endif() - elseif(SDL2_ttf_PKGCONFIG_FOUND) - message(WARNING "Found SDL2_ttf <2.0.18 - this is too old, falling back to atlas") - endif() - if(SDL2_ttf_FOUND) - list(APPEND nativeExtraLibs SDL2_ttf::SDL2_ttf) - elseif(SDL2_ttf_PKGCONFIG_FOUND) - list(APPEND nativeExtraLibs PkgConfig::SDL2_ttf_PKGCONFIG) - endif() - if(APPLE) + add_compile_definitions(SDL) list(APPEND nativeExtra - SDL/SDLMain.h - SDL/SDLMain.mm - SDL/SDLCocoaMetalLayer.h - SDL/SDLCocoaMetalLayer.mm - SDL/CocoaBarItems.mm - SDL/CocoaBarItems.h - SDL/PPSSPPAboutViewController.m - SDL/PPSSPPAboutViewController.h - SDL/MacCameraHelper.mm - Common/Battery/AppleBatteryClient.m - UI/PSPNSApplicationDelegate.mm - UI/PSPNSApplicationDelegate.h) - - # TODO - # set_source_files_properties(SDL/SDLMain.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) - - set_source_files_properties(Core/Util/DarwinFileSystemServices.mm - UI/PSPNSApplicationDelegate.mm - SDL/CocoaMetalLayer.mm + SDL/SDLJoystick.h + SDL/SDLJoystick.cpp + SDL/SDLMain.cpp + SDL/SDLGLGraphicsContext.cpp + ) + if(NOT USE_LIBNX) + list(APPEND nativeExtra + SDL/SDLVulkanGraphicsContext.cpp + ) + endif() + if(SDL2_ttf_FOUND OR + (SDL2_ttf_PKGCONFIG_FOUND AND + SDL2_ttf_PKGCONFIG_VERSION VERSION_GREATER_EQUAL "2.0.18")) + add_compile_definitions(USE_SDL2_TTF) + if(FONTCONFIG_FOUND) + add_compile_definitions(USE_SDL2_TTF_FONTCONFIG) + list(APPEND nativeExtraLibs Fontconfig::Fontconfig) + endif() + elseif(SDL2_ttf_PKGCONFIG_FOUND) + message(WARNING "Found SDL2_ttf <2.0.18 - this is too old, falling back to atlas") + endif() + if(SDL2_ttf_FOUND) + list(APPEND nativeExtraLibs SDL2_ttf::SDL2_ttf) + elseif(SDL2_ttf_PKGCONFIG_FOUND) + list(APPEND nativeExtraLibs PkgConfig::SDL2_ttf_PKGCONFIG) + endif() + if(APPLE) + list(APPEND nativeExtra + SDL/SDLMain.h + SDL/SDLMain.mm + SDL/SDLCocoaMetalLayer.h + SDL/SDLCocoaMetalLayer.mm SDL/CocoaBarItems.mm + SDL/CocoaBarItems.h SDL/PPSSPPAboutViewController.m + SDL/PPSSPPAboutViewController.h SDL/MacCameraHelper.mm Common/Battery/AppleBatteryClient.m - Common/Render/Text/draw_text_cocoa.mm - PROPERTIES COMPILE_FLAGS -fobjc-arc) - list(APPEND nativeExtraLibs ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY} "-framework AVFoundation" "-framework CoreMedia" "-framework CoreVideo") + UI/PSPNSApplicationDelegate.mm + UI/PSPNSApplicationDelegate.h) - if(USE_SYSTEM_LIBSDL2) - list(APPEND nativeExtraLibs SDL2::SDL2) + # TODO + # set_source_files_properties(SDL/SDLMain.mm PROPERTIES COMPILE_FLAGS -fobjc-arc) + + set_source_files_properties(Core/Util/DarwinFileSystemServices.mm + UI/PSPNSApplicationDelegate.mm + SDL/CocoaMetalLayer.mm + SDL/CocoaBarItems.mm + SDL/PPSSPPAboutViewController.m + SDL/MacCameraHelper.mm + Common/Battery/AppleBatteryClient.m + Common/Render/Text/draw_text_cocoa.mm + PROPERTIES COMPILE_FLAGS -fobjc-arc) + list(APPEND nativeExtraLibs ${COCOA_LIBRARY} ${QUARTZ_CORE_LIBRARY} ${IOKIT_LIBRARY} "-framework AVFoundation" "-framework CoreMedia" "-framework CoreVideo") + + if(USE_SYSTEM_LIBSDL2) + list(APPEND nativeExtraLibs SDL2::SDL2) + else() + list(APPEND nativeExtraLibs ${SDL2Fwk}) + endif() + elseif(USING_EGL) + list(APPEND nativeExtraLibs pthread SDL2::SDL2) else() - list(APPEND nativeExtraLibs ${SDL2Fwk}) + list(APPEND nativeExtraLibs SDL2::SDL2) endif() - elseif(USING_EGL) - list(APPEND nativeExtraLibs pthread SDL2::SDL2) - else() - list(APPEND nativeExtraLibs SDL2::SDL2) + elseif(NOT CMAKE_CROSSCOMPILING) + message(FATAL_ERROR "SDL2 not found - required for this platform") endif() endif() diff --git a/b.sh b/b.sh index a7202b2924..9c00794553 100755 --- a/b.sh +++ b/b.sh @@ -38,6 +38,11 @@ do --rpi64) CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/raspberry.armv8.cmake ${CMAKE_ARGS}" ;; + --loongarch64) + CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/loongarch64-linux-gnu.cmake -DHEADLESS=ON -DUSE_SYSTEM_LIBPNG=OFF -DUSE_SYSTEM_LIBSDL2=OFF ${CMAKE_ARGS}" + TARGET_OS=loongarch64 + LOONGARCH64_BUILD=1 + ;; --android) CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=android/android.toolchain.cmake ${CMAKE_ARGS}" TARGET_OS=Android PACKAGE=1 @@ -121,6 +126,33 @@ set -e echo Building with $CORES_COUNT threads mkdir -p ${BUILD_DIR} + +# For loongarch64 cross-compilation, build a comprehensive GL/GLX stub into +# /stublibs/libGL.so so GLEW's static archive can resolve its symbols +# via PLT entries (a direct B26 branch to address 0 overflows on LoongArch). +# This stub is always (re)generated to pick up any new needed symbols. +if [ ! -z "$LOONGARCH64_BUILD" ]; then + STUB_DIR=${BUILD_DIR}/stublibs + STUB_GL=${STUB_DIR}/libGL.so + mkdir -p "${STUB_DIR}" + STUB_C=$(mktemp /tmp/gl_stub_XXXXXX.c) + echo "/* Loongarch64 GL/GLX stub - cross-compilation only */" > "$STUB_C" + # Collect all T (exported) symbols from GL/GLX libs, deduplicate, emit stubs + { + for lib in /usr/lib/x86_64-linux-gnu/libGL.so.1 \ + /usr/lib/x86_64-linux-gnu/libGLX.so.0 \ + /usr/lib/x86_64-linux-gnu/libGLdispatch.so.0; do + [ -f "$lib" ] && nm -D "$lib" 2>/dev/null | awk '/^[0-9a-f]+ T /{ print $3 }' + done + # Always include the minimal GLX symbols GLEW directly references + printf '%s\n' glXGetProcAddressARB glXGetClientString glXQueryVersion \ + glBindTexture glGetString glGetIntegerv + } | sort -u | awk '{ print "void "$1"(void){}" }' >> "$STUB_C" + loongarch64-linux-gnu-gcc-14 -shared -fPIC -Wno-implicit-function-declaration \ + -o "${STUB_GL}" "$STUB_C" + rm "$STUB_C" +fi + pushd ${BUILD_DIR} cmake $CMAKE_ARGS .. diff --git a/cmake/Toolchains/loongarch64-linux-gnu.cmake b/cmake/Toolchains/loongarch64-linux-gnu.cmake new file mode 100644 index 0000000000..6338c590fb --- /dev/null +++ b/cmake/Toolchains/loongarch64-linux-gnu.cmake @@ -0,0 +1,40 @@ +set(CMAKE_SYSTEM_NAME Linux) +set(CMAKE_SYSTEM_PROCESSOR loongarch64) + +set(CMAKE_C_COMPILER loongarch64-linux-gnu-gcc-14) +set(CMAKE_CXX_COMPILER loongarch64-linux-gnu-g++-14) +set(CMAKE_ASM_COMPILER loongarch64-linux-gnu-gcc-14) + +set(CMAKE_FIND_ROOT_PATH /usr/loongarch64-linux-gnu) +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# No X11 in the sysroot; disable the X11 Vulkan path to avoid include-dir errors. +set(USING_X11_VULKAN OFF CACHE BOOL "" FORCE) + +# Bypass find_package(OpenGL REQUIRED). A stub libGL.so is required so that +# GLEW's static archive can be linked via PLT entries (direct B26 branches to +# address 0 would overflow on LoongArch). +# +# Primary: run cmake/scripts/setup-loongarch64-cross.sh (sudo) once — it +# installs the stub + GL headers into the sysroot. +# Fallback: the stub can also sit in /stublibs/libGL.so; +# b.sh --loongarch64 creates this automatically on first run. +set(OPENGL_LIBRARIES GL CACHE STRING "" FORCE) +set(CMAKE_EXE_LINKER_FLAGS + "${CMAKE_EXE_LINKER_FLAGS} -L${CMAKE_BINARY_DIR}/stublibs" + CACHE STRING "" FORCE) + +# Allow CMake's compile-check programs to run via QEMU. +# The /lib64 symlink is created by the setup script; without it, pass -L +# explicitly so QEMU can find the loongarch64 dynamic linker. +if(EXISTS "/lib64/ld-linux-loongarch-lp64d.so.1") + set(CMAKE_CROSSCOMPILING_EMULATOR "qemu-loongarch64-static" + CACHE STRING "" FORCE) +else() + set(CMAKE_CROSSCOMPILING_EMULATOR + "qemu-loongarch64-static;-L;/usr/loongarch64-linux-gnu" + CACHE STRING "" FORCE) +endif() diff --git a/cmake/scripts/setup-loongarch64-cross.sh b/cmake/scripts/setup-loongarch64-cross.sh new file mode 100755 index 0000000000..395369313b --- /dev/null +++ b/cmake/scripts/setup-loongarch64-cross.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# Sets up the loongarch64 cross-compilation environment. +# Run once with sudo. After this, ./b.sh --loongarch64 works on a fresh checkout. + +set -e + +SYSROOT=/usr/loongarch64-linux-gnu +CROSS_GCC=loongarch64-linux-gnu-gcc-14 + +if ! command -v $CROSS_GCC &>/dev/null; then + echo "Error: $CROSS_GCC not found. Install it first:" + echo " sudo apt install gcc-14-loongarch64-linux-gnu g++-14-loongarch64-linux-gnu binutils-loongarch64-linux-gnu" + exit 1 +fi + +if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run with sudo." + exit 1 +fi + +# ── OpenGL headers ─────────────────────────────────────────────────────────── +# GL headers are platform-independent C headers; copy from the host. +echo "Installing GL headers into sysroot..." +mkdir -p $SYSROOT/include/GL +for h in gl.h glext.h glcorearb.h; do + [ -f /usr/include/GL/$h ] && cp /usr/include/GL/$h $SYSROOT/include/GL/ && echo " $h" +done + +# ── GL stub library ────────────────────────────────────────────────────────── +# Generate a loongarch64 libGL.so that exports all symbols from the host +# libGL so that GLEW's static archive can be linked via PLT entries (a direct +# B26 branch to address 0 would overflow on LoongArch). +echo "Generating libGL.so stub..." + +HOST_GL="" +for candidate in \ + /usr/lib/x86_64-linux-gnu/libGL.so.1 \ + /usr/lib/x86_64-linux-gnu/libGL.so \ + /usr/lib/libGL.so.1 ; do + [ -f "$candidate" ] && HOST_GL="$candidate" && break +done + +STUB_C=$(mktemp /tmp/gl_stub_XXXXXX.c) +echo "/* Loongarch64 GL/GLX stub - for cross-compilation only */" > "$STUB_C" +echo "void __loongarch64_gl_placeholder(void) {}" >> "$STUB_C" + +if [ -n "$HOST_GL" ]; then + nm -D "$HOST_GL" 2>/dev/null | awk '/^[0-9a-f]+ T /{ print "void "$3"(void){}" }' >> "$STUB_C" + echo " Extracted symbols from $HOST_GL" +fi +# Always include the minimal set GLEW needs (in case host GL wasn't found) +for sym in glXGetProcAddressARB glXGetClientString glXQueryVersion \ + glBindTexture glGetString glGetIntegerv glGetError; do + grep -q "void ${sym}(" "$STUB_C" || echo "void ${sym}(void){}" >> "$STUB_C" +done + +$CROSS_GCC -shared -fPIC -Wno-implicit-function-declaration \ + -o $SYSROOT/lib/libGL.so "$STUB_C" +rm "$STUB_C" +echo " Installed to $SYSROOT/lib/libGL.so" + +# ── Dynamic linker symlink ─────────────────────────────────────────────────── +# Without this, binfmt_misc can't find the loongarch64 dynamic linker. +LD_LINUX=$SYSROOT/lib/ld-linux-loongarch-lp64d.so.1 +if [ -f "$LD_LINUX" ]; then + mkdir -p /lib64 + ln -sf "$LD_LINUX" /lib64/ld-linux-loongarch-lp64d.so.1 + echo "Created /lib64/ld-linux-loongarch-lp64d.so.1 -> $LD_LINUX" +fi + +echo "" +echo "Setup complete." +echo "Build: ./b.sh --loongarch64" +echo "Run: qemu-loongarch64-static -L $SYSROOT " +echo " (after setup the /lib64 symlink lets you run loongarch64 binaries directly)"