# Supermodel Libretro Core - Unified Makefile # Follows libretro/skeletor pattern with all platforms consolidated STATIC_LINKING := 0 DEBUG ?= 0 PSS_STYLE ?= 1 EXTERNAL_ZLIB ?= 0 HAVE_GRIFFIN ?= 1 # Core definitions CORE_DIR := . TARGET_NAME := supermodel # ============================================================ # Platform Auto-Detection # ============================================================ ifeq ($(platform),) platform = unix ifeq ($(shell uname -a),) platform = win else ifneq ($(findstring MINGW,$(shell uname -a)),) platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) platform = osx else ifneq ($(findstring win,$(shell uname -a)),) platform = win else ifeq ($(shell uname -m),aarch64) platform = linux-aarch64 endif endif # The libretro buildbot passes platform=win64 to the MinGW cross build, and # other spellings are in circulation too. Normalize them all to "win" so the # Windows branches below actually match -- otherwise no branch matches at all, # TARGET stays empty and "make" silently does nothing. WIN_PLATFORM := $(filter $(platform),win win32 win64 windows wincross64) ifneq (,$(WIN_PLATFORM)) platform := win endif # System platform (for native builds) system_platform = unix ifeq ($(shell uname -a),) system_platform = win else ifneq ($(findstring Darwin,$(shell uname -a)),) system_platform = osx else ifneq ($(findstring MINGW,$(shell uname -a)),) system_platform = win endif # ============================================================ # Source Files (extracted from Makefile.common) # ============================================================ LIBRETRO_COMM_DIR := $(CORE_DIR)/Src/OSD/libretro/libretro-common DEPS_DIR := $(CORE_DIR)/deps INCFLAGS := -I$(CORE_DIR) \ -I$(DEPS_DIR)/ugui \ -I$(LIBRETRO_COMM_DIR)/include \ -I$(CORE_DIR)/Src/OSD/libretro/include \ -I$(CORE_DIR)/Src/OSD/libretro \ -I$(CORE_DIR)/Src \ -I$(CORE_DIR)/Src/CPU/68K/Musashi \ -I$(CORE_DIR)/Src/CPU/68K/Musashi/generated COREDEFINES := -D__LIBRETRO__ -DSUPERMODEL_OSD_LIBRETRO -DNET_BOARD COREDEFINES += -DINLINE=inline COREDEFINES += -DPSS_STYLE=$(PSS_STYLE) # C Source Files (28 files) SOURCES_C := $(CORE_DIR)/Src/Pkgs/unzip.c \ $(CORE_DIR)/Src/Pkgs/ioapi.c \ $(CORE_DIR)/Src/CPU/68K/Musashi/m68kcpu.c \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kops.c \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopac.c \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopdm.c \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopnz.c \ $(DEPS_DIR)/ugui/ugui.c \ $(CORE_DIR)/Src/ugui_tools.c \ $(LIBRETRO_COMM_DIR)/streams/file_stream.c \ $(LIBRETRO_COMM_DIR)/streams/file_stream_transforms.c \ $(LIBRETRO_COMM_DIR)/file/file_path.c \ $(LIBRETRO_COMM_DIR)/file/file_path_io.c \ $(LIBRETRO_COMM_DIR)/file/retro_dirent.c \ $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.c \ $(LIBRETRO_COMM_DIR)/lists/dir_list.c \ $(LIBRETRO_COMM_DIR)/lists/string_list.c \ $(LIBRETRO_COMM_DIR)/string/stdstring.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strl.c \ $(LIBRETRO_COMM_DIR)/compat/fopen_utf8.c \ $(LIBRETRO_COMM_DIR)/compat/compat_strcasestr.c \ $(LIBRETRO_COMM_DIR)/compat/compat_posix_string.c \ $(LIBRETRO_COMM_DIR)/encodings/encoding_utf.c \ $(LIBRETRO_COMM_DIR)/memmap/memalign.c \ $(LIBRETRO_COMM_DIR)/time/rtime.c \ $(LIBRETRO_COMM_DIR)/hash/rhash.c # Add libretro-common glsym for non-Android ifeq (,$(findstring android,$(platform))) SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_gl.c \ $(LIBRETRO_COMM_DIR)/glsym/rglgen.c endif # C++ Source Files (80 files - verified to exist) SOURCES_CXX := $(CORE_DIR)/Src/CPU/PowerPC/PPCDisasm.cpp \ $(CORE_DIR)/Src/BlockFile.cpp \ $(CORE_DIR)/Src/Model3/93C46.cpp \ $(CORE_DIR)/Src/Util/BitRegister.cpp \ $(CORE_DIR)/Src/Model3/JTAG.cpp \ $(CORE_DIR)/Src/Pkgs/imgui/imgui.cpp \ $(CORE_DIR)/Src/Pkgs/imgui/imgui_draw.cpp \ $(CORE_DIR)/Src/Pkgs/imgui/imgui_tables.cpp \ $(CORE_DIR)/Src/Pkgs/imgui/imgui_widgets.cpp \ $(CORE_DIR)/Src/Pkgs/imgui/imgui_impl_opengl3.cpp \ $(CORE_DIR)/Src/Graphics/Legacy3D/Error.cpp \ $(CORE_DIR)/Src/Graphics/Shader.cpp \ $(CORE_DIR)/Src/Graphics/GLSLVersion.cpp \ $(CORE_DIR)/Src/Model3/Real3D.cpp \ $(CORE_DIR)/Src/Graphics/Legacy3D/Legacy3D.cpp \ $(CORE_DIR)/Src/Graphics/Legacy3D/Models.cpp \ $(CORE_DIR)/Src/Graphics/Legacy3D/TextureRefs.cpp \ $(CORE_DIR)/Src/Graphics/New3D/New3D.cpp \ $(CORE_DIR)/Src/Graphics/New3D/Mat4.cpp \ $(CORE_DIR)/Src/Graphics/New3D/Model.cpp \ $(CORE_DIR)/Src/Graphics/New3D/PolyHeader.cpp \ $(CORE_DIR)/Src/Graphics/New3D/TextureBank.cpp \ $(CORE_DIR)/Src/Graphics/New3D/VBO.cpp \ $(CORE_DIR)/Src/Graphics/New3D/Vec.cpp \ $(CORE_DIR)/Src/Graphics/New3D/R3DShader.cpp \ $(CORE_DIR)/Src/Graphics/New3D/R3DFloat.cpp \ $(CORE_DIR)/Src/Graphics/New3D/R3DScrollFog.cpp \ $(CORE_DIR)/Src/Graphics/New3D/R3DFrameBuffers.cpp \ $(CORE_DIR)/Src/Graphics/New3D/GLSLShader.cpp \ $(CORE_DIR)/Src/Graphics/FBO.cpp \ $(CORE_DIR)/Src/Graphics/SuperAA.cpp \ $(CORE_DIR)/Src/Graphics/Render2D.cpp \ $(CORE_DIR)/Src/Model3/TileGen.cpp \ $(CORE_DIR)/Src/Model3/Model3.cpp \ $(CORE_DIR)/Src/CPU/PowerPC/ppc.cpp \ $(if $(filter android aarch64 rpi64 linux-aarch64 osx,$(platform)),$(CORE_DIR)/Src/CPU/PowerPC/Jit/JitArm64.cpp,) \ $(CORE_DIR)/Src/Model3/SoundBoard.cpp \ $(CORE_DIR)/Src/Sound/SCSP.cpp \ $(CORE_DIR)/Src/Sound/SCSPDSP.cpp \ $(CORE_DIR)/Src/CPU/68K/68K.cpp \ $(CORE_DIR)/Src/Model3/DSB.cpp \ $(CORE_DIR)/Src/CPU/Z80/Z80.cpp \ $(CORE_DIR)/Src/Model3/IRQ.cpp \ $(CORE_DIR)/Src/Model3/53C810.cpp \ $(CORE_DIR)/Src/Model3/PCI.cpp \ $(CORE_DIR)/Src/Model3/RTC72421.cpp \ $(CORE_DIR)/Src/Model3/DriveBoard/DriveBoard.cpp \ $(CORE_DIR)/Src/Model3/DriveBoard/WheelBoard.cpp \ $(CORE_DIR)/Src/Model3/DriveBoard/JoystickBoard.cpp \ $(CORE_DIR)/Src/Model3/DriveBoard/SkiBoard.cpp \ $(CORE_DIR)/Src/Model3/DriveBoard/BillBoard.cpp \ $(CORE_DIR)/Src/Model3/DriveBoard/Z80CTC.cpp \ $(CORE_DIR)/Src/Model3/MPC10x.cpp \ $(CORE_DIR)/Src/Inputs/Input.cpp \ $(CORE_DIR)/Src/Inputs/Inputs.cpp \ $(CORE_DIR)/Src/Inputs/InputSource.cpp \ $(CORE_DIR)/Src/Inputs/InputSystem.cpp \ $(CORE_DIR)/Src/Inputs/InputTypes.cpp \ $(CORE_DIR)/Src/Inputs/MultiInputSource.cpp \ $(CORE_DIR)/Src/OSD/Outputs.cpp \ $(CORE_DIR)/Src/Sound/MPEG/MpegAudio.cpp \ $(CORE_DIR)/Src/Model3/Crypto.cpp \ $(CORE_DIR)/Src/OSD/Logger.cpp \ $(CORE_DIR)/Src/Util/Format.cpp \ $(CORE_DIR)/Src/Util/NewConfig.cpp \ $(CORE_DIR)/Src/Util/ByteSwap.cpp \ $(CORE_DIR)/Src/Util/ConfigBuilders.cpp \ $(CORE_DIR)/Src/GameLoader.cpp \ $(CORE_DIR)/Src/Pkgs/tinyxml2.cpp \ $(CORE_DIR)/Src/ROMSet.cpp \ $(CORE_DIR)/Src/OSD/libretro/libretroAudio.cpp \ $(CORE_DIR)/Src/OSD/libretro/libretroThread.cpp \ $(CORE_DIR)/Src/OSD/libretro/libretroCrosshair.cpp \ $(CORE_DIR)/Src/OSD/libretro/libretroGui.cpp \ $(CORE_DIR)/Src/OSD/libretro/LibretroBlockFileMemory.cpp \ $(CORE_DIR)/Src/OSD/libretro/CLibretroInputSystem.cpp \ $(CORE_DIR)/Src/OSD/libretro/CLibretroOutputSystem.cpp \ $(CORE_DIR)/Src/OSD/libretro/LibretroNetBoard.cpp \ $(CORE_DIR)/Src/OSD/libretro/LibretroWrapper.cpp \ $(CORE_DIR)/Src/OSD/libretro/vfs_ioapi.cpp \ $(CORE_DIR)/Src/OSD/libretro/libretro.cpp # Platform-specific OSD FileSystemPath implementation ifeq ($(platform),win) SOURCES_CXX += $(CORE_DIR)/Src/OSD/Windows/FileSystemPath.cpp else ifeq ($(platform),osx) SOURCES_CXX += $(CORE_DIR)/Src/OSD/OSX/FileSystemPath.cpp else # osx, unix, android, rpi64, aarch64 all use Unix FileSystemPath SOURCES_CXX += $(CORE_DIR)/Src/OSD/Unix/FileSystemPath.cpp endif # Renderer selection: new3d (default) or legacy. # make platform=rpi64 RENDERER=legacy # Legacy3D is the old desktop-GL renderer. It is being ported to run inside the # GLES3 context (GLES2-style code: client vertex arrays, #version 100 shaders), # so on GLES platforms it is only compiled in when explicitly asked for. RENDERER ?= new3d LEGACY3D_SOURCES := %/Legacy3D/Error.cpp %/Legacy3D/Legacy3D.cpp %/Legacy3D/Models.cpp %/Legacy3D/TextureRefs.cpp # These platforms always omit the Legacy3D sources (see below). Reject an # explicit legacy build up front instead of failing at link time on CLegacy3D. ifneq ($(filter $(platform),osx android ios-arm64 tvos-arm64),) ifeq ($(RENDERER),legacy) $(error RENDERER=legacy is not supported for platform=$(platform)) endif endif ifeq ($(RENDERER),legacy) RENDERER_DEFINES := -DUSE_LEGACY3D DROP_LEGACY3D := else RENDERER_DEFINES := DROP_LEGACY3D := 1 endif # Platform-specific source filtering (MUST be before OBJECTS computation!) # macOS and Android don't support Legacy3D (old fixed-pipeline OpenGL) ifeq ($(platform),osx) SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX)) endif ifeq ($(platform),android) SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX)) endif # rpi64 and aarch64 use GLES3 (RetroArch on RPi5 provides only GLES context via EGL) ifeq ($(platform),rpi64) SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C)) SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c ifdef DROP_LEGACY3D SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX)) endif endif ifeq ($(platform),aarch64) SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C)) SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c ifdef DROP_LEGACY3D SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX)) endif endif ifeq ($(platform),linux-aarch64) SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C)) SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c ifdef DROP_LEGACY3D SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX)) endif endif # iOS and tvOS are GLES too, and there is no desktop GL on either to fall back # on, so Legacy3D goes whatever RENDERER says, as it does for osx and android. ifneq ($(filter $(platform),ios-arm64 tvos-arm64),) SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C)) SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c SOURCES_CXX := $(filter-out $(LEGACY3D_SOURCES),$(SOURCES_CXX)) endif # Tell the Libretro option layer whether Legacy3D is in this build, after all the # platform filtering above, so the 3D Renderer option only appears where it works. ifneq ($(filter %/Legacy3D/Legacy3D.cpp,$(SOURCES_CXX)),) RENDERER_DEFINES += -DHAVE_LEGACY3D endif # GIT version GIT_VERSION := " $(shell git rev-parse --short HEAD || echo unknown)" ifneq ($(GIT_VERSION)," unknown") COREDEFINES += -DGIT_VERSION=\"$(GIT_VERSION)\" endif # Platform-specific defines (to be assembled with COREDEFINES into final DEFINES) PLATFORM_DEFINES := # ============================================================ # Platform-Specific Configuration # ============================================================ # ============ UNIX/LINUX (Default) ============ ifeq ($(platform),unix) TARGET := $(TARGET_NAME)_libretro.so LDFLAGS += -shared -fPIC CFLAGS += -fPIC CXXFLAGS += -fPIC # Legacy3D uses GLU's perspective helper. Unlike desktop OpenGL entry # points supplied by the Libretro frontend, GLU is not guaranteed to be # exported by the frontend process and must be an explicit dependency. LIBS += -ldl -lm -lz -lGLU ifeq ($(strip $(CROSS_COMPILE)),) INCFLAGS += -I/usr/include endif endif # ============ Linux ARM64 (native — CI runner, RPi4/5, ARM64 SBCs) ============ # Auto-selected when platform is unset and uname -m is aarch64. # Uses the native compiler; enables GLES3 + JIT (required for RetroArch on RPi). # For cross-compiling from x86 to RPi, use platform=rpi64 instead. ifeq ($(platform),linux-aarch64) TARGET := $(TARGET_NAME)_libretro.so fpic := -fPIC SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,-no-undefined LDFLAGS += $(SHARED) CFLAGS += -fPIC CXXFLAGS += -fPIC LIBS += -ldl -lm -lz PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_ CXXFLAGS += -std=c++17 endif # ============ iOS / tvOS (arm64) ============ # Both are the GLES build with Apple's SDK in front of it: the renderer resolves # every entry point through glsym, so nothing links against a GL framework here # any more than it does on the other GLES platforms, and OpenGLES is deprecated # on these systems anyway. # # No PPC JIT. Writing and then executing the same page needs an entitlement that # a libretro core cannot ask for on stock iOS or tvOS, so the recompiler is out # and Model 3 runs on the interpreter. That is the same bargain every emulator # on these systems makes, and it is the reason to be honest about what the # artifact is rather than to leave the platform unbuilt. # # The dylib names are what the libretro ios-arm64 and tvos-arm64 templates look # for, and their after_script checks the platform recorded in the Mach-O, which # is what -isysroot and the version-min flag put there. ifneq ($(filter $(platform),ios-arm64 tvos-arm64),) ifeq ($(platform),ios-arm64) TARGET := $(TARGET_NAME)_libretro_ios.dylib APPLE_SDK := $(shell xcrun -sdk iphoneos -show-sdk-path) APPLE_MIN := -miphoneos-version-min=13.0 PLATFORM_DEFINES += -DIOS else TARGET := $(TARGET_NAME)_libretro_tvos.dylib APPLE_SDK := $(shell xcrun -sdk appletvos -show-sdk-path) APPLE_MIN := -mappletvos-version-min=13.0 PLATFORM_DEFINES += -DTVOS endif # Same lesson as the bundled headers above: a tool that is not there should # stop the build where it is missing, not hand the compiler an empty # -isysroot and let it fail later on a header it cannot find. ifeq ($(APPLE_SDK),) $(error xcrun found no SDK for $(platform) - is Xcode installed and selected?) endif CC := clang CXX := clang++ ARCHFLAGS := -arch arm64 -isysroot $(APPLE_SDK) $(APPLE_MIN) CFLAGS += -fPIC $(ARCHFLAGS) CXXFLAGS += -fPIC $(ARCHFLAGS) -std=c++17 LDFLAGS += -dynamiclib -fPIC $(ARCHFLAGS) # dlopen lives in libc on these systems, so there is no -ldl to link. LIBS += -lm -lz PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_ PLATFORM_DEFINES += -DGL_SILENCE_DEPRECATION endif # ============ macOS / osxcross ============ ifeq ($(platform),osx) TARGET := $(TARGET_NAME)_libretro.dylib # __gcov_dump is an optional profiling hook. Keep only that symbol weakly # importable so missing core dependencies still fail at link time. LDFLAGS += -dynamiclib -fPIC -Wl,-U,___gcov_dump CFLAGS += -fPIC CXXFLAGS += -fPIC LIBS += -lm -framework OpenGL -framework CoreFoundation PLATFORM_DEFINES += -DGL_SILENCE_DEPRECATION ifeq ($(system_platform),osx) # Native macOS build (CI macOS runner or local Mac developer build). # Build for the host arch so the CI x64 job → x86_64, arm64 job → arm64. NATIVE_ARCH := $(shell uname -m) ARCHFLAGS := -arch $(NATIVE_ARCH) -mmacosx-version-min=10.15 CFLAGS += $(ARCHFLAGS) CXXFLAGS += $(ARCHFLAGS) LDFLAGS += $(ARCHFLAGS) # Apple Silicon requires MAP_JIT plus per-thread W^X switching. Keep # Intel and universal cross-builds on the interpreter. ifeq ($(NATIVE_ARCH),arm64) PLATFORM_DEFINES += -DHAVE_PPC_JIT endif else # Cross-compile from Linux via osxcross (universal x86_64 + arm64 dylib). OSXCROSS_ROOT ?= /opt/osxcross OSXCROSS_PATH := $(OSXCROSS_ROOT)/target/bin ifeq ($(wildcard $(OSXCROSS_PATH)/o64-clang++),) $(error osxcross not found at $(OSXCROSS_ROOT). Install: cd /tmp && git clone https://github.com/tpoechtrager/osxcross.git && cd osxcross && wget -nc https://github.com/rtrussell/osxcross-build/releases/download/12.0/MacOSX12.0.sdk.tar.xz -O tarballs/MacOSX12.0.sdk.tar.xz && ./build.sh) endif export PATH := $(OSXCROSS_PATH):$(PATH) export LD_LIBRARY_PATH := $(OSXCROSS_ROOT)/target/lib:$(LD_LIBRARY_PATH) override CC := o64-clang override CXX := o64-clang++ override LD := o64-clang++ ARCHFLAGS := -arch x86_64 -arch arm64 CFLAGS += $(ARCHFLAGS) CXXFLAGS += $(ARCHFLAGS) LDFLAGS += $(ARCHFLAGS) MACOSX_SDK ?= /opt/osxcross/target/SDK/MacOSX12.0.sdk CFLAGS += -isysroot $(MACOSX_SDK) CXXFLAGS += -isysroot $(MACOSX_SDK) LDFLAGS += -isysroot $(MACOSX_SDK) LDFLAGS += -static-libstdc++ endif endif # ============ ANDROID ============ ifeq ($(platform),android) TARGET := $(TARGET_NAME)_libretro_android.so fpic := -fPIC SHARED := -shared PLATFORM_DEFINES += -DANDROID -D__LIBRETRO__ -DPSS_STYLE=1 -D_FILE_OFFSET_BITS=64 PLATFORM_DEFINES += -D_POSIX_C_SOURCE=200809L -D_GNU_SOURCE PLATFORM_DEFINES += -DEGL_EGLEXT_PROTOTYPES LIBS += -lGLESv3 -llog -lz # Prepend Android shim headers to resolve to our shim INCFLAGS := -I$(CORE_DIR)/Src/OSD/Android/include $(INCFLAGS) # --- NDK Detection --- # Check common locations if NDK_ROOT is not already set ifeq ($(NDK_ROOT),) NDK_ROOT := $(shell ls -d ~/Android/Sdk/ndk/28.2.13676358 2>/dev/null) endif # Performance Flags from Mupen64Plus HAVE_NEON := 0 ifeq ($(arch),arm) HAVE_NEON := 1 endif ifeq ($(arch),arm64) HAVE_NEON := 1 endif # LTO Control - Disable for Android due to PIC relocation issues with NDK clang HAVE_LTCG := 0 # If NDK is found, use its Clang toolchain ifneq ($(NDK_ROOT),) # Default to aarch64 (64-bit ARM) if no 'arch' is specified ifeq ($(arch),arm) ARCH_TRIPLE := arm-linux-androideabi CLANG_TRIPLE := armv7a-linux-androideabi24 PLATFORM_DEFINES += -march=armv7-a -mfloat-abi=softfp -mfpu=neon else ifeq ($(arch),x86) ARCH_TRIPLE := i686-linux-android CLANG_TRIPLE := i686-linux-android24 else ifeq ($(arch),x86_64) ARCH_TRIPLE := x86_64-linux-android CLANG_TRIPLE := x86_64-linux-android24 else # Default to arm64 (aarch64) ARCH_TRIPLE := aarch64-linux-android CLANG_TRIPLE := aarch64-linux-android24 PLATFORM_DEFINES += -DHAVE_PPC_JIT endif TOOLCHAIN := $(NDK_ROOT)/toolchains/llvm/prebuilt/linux-x86_64/bin CC := $(TOOLCHAIN)/$(CLANG_TRIPLE)-clang CXX := $(TOOLCHAIN)/$(CLANG_TRIPLE)-clang++ LD := $(CXX) # Android Clang usually needs some extra flags CFLAGS += -ffunction-sections -fdata-sections CXXFLAGS += -ffunction-sections -fdata-sections LDFLAGS += $(SHARED) -Wl,-soname,$(TARGET) -Wl,--no-undefined # Link C++ library statically to avoid dlopen issues on device LDFLAGS += -static-libstdc++ else # Fallback to generic names if NDK not found CC = arm-linux-androideabi-gcc CXX = arm-linux-androideabi-g++ LD := $(CXX) endif ifeq ($(HAVE_NEON),1) PLATFORM_DEFINES += -DHAVE_NEON -D__ARM_NEON__ -ftree-vectorize endif OBJOUT = -o LINKOUT = -o LIBM := -lm WARNING_DEFINES := -Wno-write-strings # Ensure CXXFLAGS is appended CXXFLAGS += -std=c++17 ifeq ($(DEBUG),1) CFLAGS += -O0 -g -DDEBUG CXXFLAGS += -O0 -g -DDEBUG else CFLAGS += -O3 -DNDEBUG CXXFLAGS += -O3 -DNDEBUG # General Performance Optimizations CFLAGS += -ffast-math -funsafe-math-optimizations -fomit-frame-pointer CXXFLAGS += -ffast-math -funsafe-math-optimizations -fomit-frame-pointer # Visibility Optimizations CFLAGS += -fvisibility=hidden CXXFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden # LTO (Link Time Optimization) ifeq ($(HAVE_LTCG),1) CFLAGS += -flto CXXFLAGS += -flto LDFLAGS += -flto endif endif endif # ============ WINDOWS / MinGW ============ ifeq ($(platform),win) TARGET := $(TARGET_NAME)_libretro.dll LDFLAGS += -shared CFLAGS += -D_WIN32 -DWIN32 CXXFLAGS += -D_WIN32 -DWIN32 ifeq ($(system_platform),win) # Native Windows build with MinGW ifeq ($(origin CC),default) CC := gcc endif ifeq ($(origin CXX),default) CXX := g++ endif else # Cross-compile to Windows (from Linux). Only fall back to the plain # mingw-w64 names when no toolchain was handed to us -- the buildbot's # MXE container exports its own (x86_64-w64-mingw32.static-gcc), and # overriding that would point us at compilers that do not exist there. ifeq ($(WIN_PLATFORM),win32) MINGW_PREFIX ?= i686-w64-mingw32 else MINGW_PREFIX ?= x86_64-w64-mingw32 endif ifeq ($(origin CC),default) CC := $(MINGW_PREFIX)-gcc endif ifeq ($(origin CXX),default) CXX := $(MINGW_PREFIX)-g++ endif ifeq ($(origin AR),default) AR := $(MINGW_PREFIX)-ar endif endif # Static-link MinGW runtimes and zlib so the DLL is self-contained — no # libgcc_s_seh-1.dll / libstdc++-6.dll / zlib1.dll required on the user's system. LDFLAGS += -static-libgcc -static-libstdc++ LIBS += -lm -Wl,-Bstatic -lz -Wl,-Bdynamic -lopengl32 -lglu32 -lgdi32 endif # ============ Raspberry Pi 64-bit ============ ifeq ($(platform),rpi64) CC = aarch64-linux-gnu-gcc CXX = aarch64-linux-gnu-g++ LD = aarch64-linux-gnu-g++ TARGET := $(TARGET_NAME)_libretro_aarch64.so fpic := -fPIC SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,-no-undefined # 1. ARCHITECTURE & FEATURE FLAGS PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -funsafe-math-optimizations # Prevent system header redeclaration PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_ # 2. CPU TUNING # platform=rpi64 always matches above, so the specific board must be # selected via board=rpi5 / board=rpi4 (e.g. make platform=rpi64 board=rpi5) ifeq ($(board), rpi5) PLATFORM_DEFINES += -mcpu=cortex-a76 else ifeq ($(board), rpi4) PLATFORM_DEFINES += -mcpu=cortex-a72 else PLATFORM_DEFINES += -mcpu=cortex-a53 endif # 3. LIBRARY & PATHS LDFLAGS += $(SHARED) -L/usr/lib/aarch64-linux-gnu LIBS := -lGLESv2 -lz -lm # 4. CXXFLAGS CXXFLAGS += -std=c++17 endif # ============ aarch64 (Generic ARM64) ============ ifeq ($(platform),aarch64) CC = aarch64-linux-gnu-gcc CXX = aarch64-linux-gnu-g++ LD = aarch64-linux-gnu-g++ TARGET := $(TARGET_NAME)_libretro.so fpic := -fPIC SHARED := -shared -Wl,--version-script=$(CORE_DIR)/link.T -Wl,-no-undefined # 1. ARCHITECTURE & FEATURE FLAGS PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -funsafe-math-optimizations # Prevent system header redeclaration PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_ # 2. LIBRARY & PATHS LDFLAGS += $(SHARED) -L/usr/lib/aarch64-linux-gnu LIBS := -lGLESv2 -lz -lm # 3. CXXFLAGS CXXFLAGS += -std=c++17 endif # ============ webOS ============ ifneq (,$(or $(findstring webos,$(CROSS_COMPILE)),$(findstring starfish,$(CROSS_COMPILE)))) SOURCES_C := $(filter-out %/glsym/glsym_gl.c,$(SOURCES_C)) SOURCES_C += $(LIBRETRO_COMM_DIR)/glsym/glsym_es3.c # 1. ARCHITECTURE & FEATURE FLAGS ifneq (,$(findstring aarch64,$(CROSS_COMPILE))) PLATFORM_DEFINES += -DARM -D__aarch64__ -DLSB_FIRST -DGL_GLEXT_PROTOTYPES -DHAVE_PPC_JIT endif PLATFORM_DEFINES += -fomit-frame-pointer -ffast-math -funsafe-math-optimizations # Prevent system header redeclaration PLATFORM_DEFINES += -DGLES -Dgles -DHAVE_OPENGLES=1 -DHAVE_OPENGLES3=1 -DCORE_GLES -D__glext_h_ -D__GLEXT_H_ # 2. LIBRARY & PATHS LIBS := -lGLESv2 -lz -lm endif OBJECTS := $(SOURCES_C:.c=.o) $(SOURCES_CXX:.cpp=.o) DEPFILES := $(OBJECTS:.o=.d) # ============ COMMON COMPILER FLAGS ============ # C compiler defaults CC ?= gcc CXX ?= g++ AR ?= ar # Assemble final DEFINES from COREDEFINES and PLATFORM_DEFINES (mirrors old build system) DEFINES := $(COREDEFINES) $(PLATFORM_DEFINES) $(RENDERER_DEFINES) OBJOUT ?= -o LINKOUT ?= -o LIBM ?= -lm WARNING_DEFINES ?= -Wno-write-strings # Base optimization and warning flags CFLAGS := $(CFLAGS) -Wall -Wextra -O3 -ffast-math -DHAVE_ZLIB $(fpic) CXXFLAGS := $(CXXFLAGS) -Wall -Wextra -std=c++17 -O3 -ffast-math -DHAVE_ZLIB $(fpic) # Include path flags and final defines assembly CFLAGS += $(INCFLAGS) $(DEFINES) CXXFLAGS += $(INCFLAGS) $(DEFINES) # Debug settings ifeq ($(DEBUG),1) CFLAGS := $(filter-out -O3,$(CFLAGS)) -g -O0 -DDEBUG CXXFLAGS := $(filter-out -O3,$(CXXFLAGS)) -g -O0 -DDEBUG LDFLAGS += -g endif # External zlib ifeq ($(EXTERNAL_ZLIB),1) INCFLAGS += $(shell pkg-config --cflags zlib) LIBS += $(shell pkg-config --libs zlib) else LIBS += -lz endif # ============================================================ # Build Rules # ============================================================ .DEFAULT_GOAL := all BUNDLED_GAMES_XML_H := $(CORE_DIR)/Src/OSD/libretro/BundledGamesXml.h BUNDLED_SUPERMODEL_H := $(CORE_DIR)/Src/OSD/libretro/BundledSupermodelIni.h $(CORE_DIR)/Src/OSD/libretro/LibretroWrapper.o: \ $(BUNDLED_GAMES_XML_H) \ $(BUNDLED_SUPERMODEL_H) .PHONY: all clean info $(info PLATFORM_DEFINES ARE: $(PLATFORM_DEFINES)) all: $(BUNDLED_GAMES_XML_H) $(BUNDLED_SUPERMODEL_H) $(TARGET) $(BUNDLED_GAMES_XML_H): $(CORE_DIR)/Config/Games.xml xxd -i $< | sed 's/unsigned char.*\[\]/const unsigned char bundled_games_xml[]/' \ | sed 's/unsigned int.*_len/const unsigned int bundled_games_xml_len/' > $@ $(BUNDLED_SUPERMODEL_H): $(CORE_DIR)/Config/Supermodel.ini xxd -i $< | sed 's/unsigned char.*\[\]/const unsigned char bundled_supermodel_ini[]/' \ | sed 's/unsigned int.*_len/const unsigned int bundled_supermodel_ini_len/' > $@ -include $(DEPFILES) $(TARGET): $(OBJECTS) @echo "Linking $(TARGET)..." $(CXX) $(LDFLAGS) $(OBJECTS) $(LIBS) -o $@ @echo "Build complete: $@" # Special handling for ppc.o: strip -ffast-math to avoid FENV_ACCESS pragma conflicts # ppc_ops.c contains #pragma STDC FENV_ACCESS ON which requires precise FP semantics # For Android DEBUG builds, also ensure -fPIC is applied to prevent relocation errors $(CORE_DIR)/Src/CPU/PowerPC/ppc.o: CXXFLAGS := $(filter-out -ffast-math -funsafe-math-optimizations,$(CXXFLAGS)) $(CORE_DIR)/Src/CPU/PowerPC/ppc.o: CXXFLAGS += -Wno-unused-parameter # Both 3D renderers explicitly sanitize NaN/Inf fog values used by Star Wars # Trilogy. -ffinite-math-only (part of -ffast-math) removes those checks, so # keep the rest of fast-math but allow non-finite values in these files. IEEE_FP_RENDERER_OBJECTS := $(CORE_DIR)/Src/Graphics/New3D/New3D.o \ $(CORE_DIR)/Src/Graphics/Legacy3D/Legacy3D.o $(IEEE_FP_RENDERER_OBJECTS): CXXFLAGS += -fno-finite-math-only ifeq ($(platform),android) ifeq ($(DEBUG),1) $(CORE_DIR)/Src/CPU/PowerPC/ppc.o: CXXFLAGS += -fPIC endif endif # These vendored/generated sources intentionally expose platform-dependent # parameters and legacy implementation details that are unused by this core. # Keep their known warning noise local instead of weakening warnings globally. MUSASHI_OBJECTS := $(CORE_DIR)/Src/CPU/68K/Musashi/m68kcpu.o \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kops.o \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopac.o \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopdm.o \ $(CORE_DIR)/Src/CPU/68K/Musashi/generated/m68kopnz.o LIBRETRO_COMMON_WARNING_OBJECTS := $(LIBRETRO_COMM_DIR)/file/file_path.o \ $(LIBRETRO_COMM_DIR)/file/retro_dirent.o \ $(LIBRETRO_COMM_DIR)/vfs/vfs_implementation.o \ $(LIBRETRO_COMM_DIR)/string/stdstring.o $(MUSASHI_OBJECTS): CFLAGS += -Wno-unused-parameter $(DEPS_DIR)/ugui/ugui.o: CFLAGS += -Wno-sign-compare -Wno-bitwise-op-parentheses -Wno-unused-but-set-variable $(LIBRETRO_COMMON_WARNING_OBJECTS): CFLAGS += -Wno-unused-parameter -Wno-sign-compare %.o: %.c $(CC) $(CFLAGS) -MMD -MP -c -o $@ $< %.o: %.cpp $(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $< clean: @echo "Cleaning..." @rm -f $(OBJECTS) $(DEPFILES) $(TARGET) @echo "Clean complete" info: @echo "Platform: $(platform)" @echo "Target: $(TARGET)" @echo "CC: $(CC)" @echo "CXX: $(CXX)" @echo "CFLAGS: $(CFLAGS)" @echo "CXXFLAGS: $(CXXFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" @echo "LIBS: $(LIBS)"