From 94b33c924e0524452738e077aea03ba7e8b6302f Mon Sep 17 00:00:00 2001
From: Nadia Holmquist Pedersen <nadia@nhp.sh>
Date: Sat, 21 May 2022 19:54:55 +0200
Subject: [PATCH] Modernize CMake build system (#1434)

These changes modernize the CMake build system to (hopefully) match newer best practices

* Library linking is simpler and more automatic because of using imported targets
* Multi-configuration builds should be supported (Ninja Multi-Config, Visual Studio, etc. generators)
* Clean up build options using cmake_dependent_option
* Let CMake do its job in more cases, like finding the math/dl libraries and detecting and enabling LTO support
* Remove platform-specific kludges like the Fedora/flatpak LTO workaround and a bunch of Windows stuff
* Simplify Windows static builds
* Consistent formatting
---
 .github/workflows/build-windows.yml |   2 +-
 CMakeLists.txt                      | 126 ++++++---------
 README.md                           |  82 +++++-----
 cmake/FixInterfaceIncludes.cmake    |  28 ++++
 res/melon.plist.in                  |   4 +-
 res/melon.rc.in                     |   8 +-
 src/CMakeLists.txt                  | 228 ++++++++++++++--------------
 src/frontend/qt_sdl/CMakeLists.txt  | 103 +++++--------
 8 files changed, 275 insertions(+), 306 deletions(-)
 create mode 100644 cmake/FixInterfaceIncludes.cmake

diff --git a/.github/workflows/build-windows.yml b/.github/workflows/build-windows.yml
index a4026a7b..bf44f6de 100644
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -35,7 +35,7 @@ jobs:
 
     - name: Configure
       working-directory: ${{runner.workspace}}/build
-      run: cmake $GITHUB_WORKSPACE -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_STATIC=ON -DQT5_STATIC_DIR=C:/tools/msys64/mingw64/qt5-static
+      run: cmake $GITHUB_WORKSPACE -G 'MSYS Makefiles' -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DBUILD_STATIC=ON -DCMAKE_PREFIX_PATH=C:/tools/msys64/mingw64/qt5-static
 
     - name: Make
       working-directory: ${{runner.workspace}}/build
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60dac082..74aaf422 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,43 +1,38 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.15)
 
-include(CheckSymbolExists)
-include(CheckLibraryExists)
-
-cmake_policy(VERSION 3.13)
+cmake_policy(VERSION 3.15)
 if (POLICY CMP0076)
     cmake_policy(SET CMP0076 NEW)
 endif()
 
+set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
+
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
+
+project(melonDS
+    VERSION 0.9.4
+    DESCRIPTION "DS emulator, sorta"
+    HOMEPAGE_URL "https://melonds.kuribo64.net"
+    LANGUAGES C CXX)
+
+include(CheckSymbolExists)
+include(CheckLibraryExists)
+include(CMakeDependentOption)
+include(CheckIPOSupported)
+
 set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
 
-project(melonDS CXX)
-
 set(CMAKE_C_STANDARD 11)
+set(CMAKE_C_STANDARD_REQUIRED ON)
 set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
 
-set(MELONDS_VERSION "0.9.4")
-add_compile_definitions(MELONDS_VERSION="${MELONDS_VERSION}")
-string(REPLACE "." ";" VERSION_LIST ${MELONDS_VERSION})
-# For the melon.rc file used on Windows
-list(GET VERSION_LIST 0 MELONDS_VERSION_MAJOR)
-list(GET VERSION_LIST 1 MELONDS_VERSION_MINOR)
-# Check if melonDS version is three digits or two digits
-list(LENGTH VERSION_LIST MELONDS_VER_LEN)
-if (${MELONDS_VER_LEN} GREATER 2) 
-    list(GET VERSION_LIST 2 MELONDS_VERSION_PATCH)
-else()
-    set(MELONDS_VERSION_PATCH 0)
-endif()
+add_compile_definitions(MELONDS_VERSION="${melonDS_VERSION}")
 
-
-check_library_exists(m pow "" LIBM)
-if(LIBM)
-    link_libraries(m)
-endif()
-
-if (NOT CMAKE_BUILD_TYPE)
-    set(CMAKE_BUILD_TYPE Release)
+if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
+    set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
+    set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
 endif()
 
 function(detect_architecture symbol arch)
@@ -61,74 +56,41 @@ detect_architecture("__i386__" x86)
 detect_architecture("__arm__" ARM)
 detect_architecture("__aarch64__" ARM64)
 
-if (ARCHITECTURE STREQUAL x86_64 OR ARCHITECTURE STREQUAL ARM64)
-	option(ENABLE_JIT "Enable x64 JIT recompiler" ON)
-endif()
-
-if (ENABLE_JIT)
-	add_definitions(-DJIT_ENABLED)
-
-	option(ENABLE_JIT_PROFILING "Enable JIT profiling with VTune" OFF)
-
-	if (ENABLE_JIT_PROFILING)
-		include(cmake/FindVTune.cmake)
-		add_definitions(-DJIT_PROFILING_ENABLED)
-	endif()
-endif()
-
-if (CMAKE_BUILD_TYPE STREQUAL Release)
-	option(ENABLE_LTO "Enable link-time optimization" ON)
-else()
-	option(ENABLE_LTO "Enable link-time optimization" OFF)
-endif()
-
+cmake_dependent_option(ENABLE_JIT "Enable JIT recompiler" ON
+    "ARCHITECTURE STREQUAL x86_64 OR ARCHITECTURE STREQUAL ARM64" OFF)
+cmake_dependent_option(ENABLE_JIT_PROFILING "Enable JIT profiling with VTune" OFF "ENABLE_JIT" OFF)
 option(ENABLE_OGLRENDERER "Enable OpenGL renderer" ON)
 
-if (ENABLE_OGLRENDERER)
-    add_definitions(-DOGLRENDERER_ENABLED)
+check_ipo_supported(RESULT IPO_SUPPORTED)
+cmake_dependent_option(ENABLE_LTO_RELEASE "Enable link-time optimizations for release builds" ON "IPO_SUPPORTED" OFF)
+cmake_dependent_option(ENABLE_LTO "Enable link-time optimizations" OFF "IPO_SUPPORTED" OFF)
+
+if (ENABLE_LTO_RELEASE)
+    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
 endif()
 
-if (CMAKE_BUILD_TYPE STREQUAL Debug)
-	add_compile_options(-Og)
+if (ENABLE_LTO)
+    set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
 endif()
 
-if (CMAKE_BUILD_TYPE STREQUAL Release)
-	add_compile_options(-O3)
-	if (NOT APPLE)
-		add_link_options(-s)
-	endif()
+set(CMAKE_C_FLAGS_DEBUG "-Og")
+set(CMAKE_CXX_FLAGS_DEBUG "-Og")
+set(CMAKE_C_FLAGS_RELEASE "-O3")
+set(CMAKE_CXX_FLAGS_RELEASE "-O3")
+
+if (NOT APPLE)
+    set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -s")
 endif()
 
 if (WIN32)
-	option(BUILD_STATIC "Statically link dependencies" OFF)
+    option(BUILD_STATIC "Statically link dependencies" OFF)
 endif()
 
 if (BUILD_STATIC AND WIN32)
     set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
 endif()
 
-if (ENABLE_LTO)
-	if (WIN32 OR APPLE)
-		add_compile_options(-flto)
-		add_link_options(-flto)
-	else()
-		add_compile_options(-flto -fPIC)
-		add_link_options(-flto -fuse-linker-plugin -pie)
-	endif()
-	if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
-		set(CMAKE_AR "gcc-ar")
-		set(CMAKE_RANLIB "gcc-ranlib")
-	elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
-		find_program(LLD NAMES ld.lld ld64.lld lld-link)
-		if (NOT LLD STREQUAL "LLD-NOTFOUND")
-			add_link_options(-fuse-ld=lld)
-		endif()
-		if (NOT APPLE)
-			set(CMAKE_AR "llvm-ar")
-			set(CMAKE_RANLIB "llvm-ranlib")
-		endif()
-	endif()
-endif()
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 
 find_program(CCACHE "ccache")
 if (CCACHE)
@@ -142,5 +104,5 @@ option(BUILD_QT_SDL "Build Qt/SDL frontend" ON)
 add_subdirectory(src)
 
 if (BUILD_QT_SDL)
-	add_subdirectory(src/frontend/qt_sdl)
+    add_subdirectory(src/frontend/qt_sdl)
 endif()
diff --git a/README.md b/README.md
index 61e9c963..4e28439e 100644
--- a/README.md
+++ b/README.md
@@ -34,69 +34,75 @@ As for the rest, the interface should be pretty straightforward. If you have a q
 
 ## How to build
 
-### Linux:
+### Linux
+1. Install dependencies:
+   * Ubuntu 22.04: `sudo apt install cmake libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qtbase5-dev libslirp-dev libarchive-dev libepoxy-dev`
+   * Older Ubuntu: `sudo apt install cmake libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qt5-default libslirp-dev libarchive-dev libepoxy-dev`
+   * Arch Linux: `sudo pacman -S base-devel cmake git libpcap sdl2 qt5-base libslirp libarchive libepoxy`
+3. Download the melonDS repository and prepare:
+   ```bash
+   git clone https://github.com/Arisotura/melonDS
+   cd melonDS
+   ```
 
-1. Install dependencies (for example on Debian/Ubuntu: `sudo apt install cmake libcurl4-gnutls-dev libpcap0.8-dev libsdl2-dev qtbase5-dev libslirp-dev libarchive-dev libepoxy-dev`)
-2. Download the melonDS repository and prepare:
-  ```bash
-  git clone https://github.com/Arisotura/melonDS
-  cd melonDS
-  mkdir build && cd build
-  ```
 3. Compile:
-  ```bash
-  cmake ..
-  make -j$(nproc --all)
-  ```
-
-### Windows:
+   ```bash
+   cmake -B build
+   cmake --build build -j$(nproc --all)
+   ```
 
+### Windows
 1. Install [MSYS2](https://www.msys2.org/)
 2. Open the **MSYS2 MinGW 64-bit** terminal
 3. Update the packages using `pacman -Syu` and reopen the terminal if it asks you to
-4. Download the melonDS repository and prepare:
-  ```bash
-  git clone https://github.com/Arisotura/melonDS
-  cd melonDS
-  mkdir build && cd build
-  ```
+4. Install git to clone the repository
+   ```bash
+   pacman -S git
+   ```
+5. Download the melonDS repository and prepare:
+   ```bash
+   git clone https://github.com/Arisotura/melonDS
+   cd melonDS
+   ```
 #### Dynamic builds (with DLLs)
-5. Install dependencies: `pacman -S git make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain,qt5,libslirp,libarchive,libepoxy}`
+5. Install dependencies: `pacman -S make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain,qt5,libslirp,libarchive,libepoxy}`
 6. Compile:
    ```bash
-   cmake .. -G "MSYS Makefiles"
-   make -j$(nproc --all)
+   cmake -B build -G "MSYS Makefiles"
+   cmake --build build -j$(nproc --all)
+   cd build
    ../tools/msys-dist.sh
    ```
 If everything went well, melonDS and the libraries it needs should now be in the `dist` folder.
 
 #### Static builds (without DLLs, standalone executable)
-5. Install dependencies: `pacman -S git make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain,qt5-static,libslirp,libarchive,libepoxy}`
+5. Install dependencies: `pacman -S make mingw-w64-x86_64-{cmake,mesa,SDL2,toolchain,qt5-static,libslirp,libarchive,libepoxy}`
 6. Compile:
    ```bash
-   cmake .. -G 'MSYS Makefiles' -DBUILD_STATIC=ON -DQT5_STATIC_DIR=/mingw64/qt5-static
-   make -j$(nproc --all)
-   mkdir dist && cp melonDS.exe dist
+   cmake -B build -G 'MSYS Makefiles' -DBUILD_STATIC=ON -DCMAKE_PREFIX_PATH=/mingw64/qt5-static
+   cmake --build build -j$(nproc --all)
    ```
-If everything went well, melonDS should now be in the `dist` folder.
+If everything went well, melonDS should now be in the `build` folder.
 
-### macOS:
+### macOS
 1. Install the [Homebrew Package Manager](https://brew.sh)
 2. Install dependencies: `brew install git pkg-config cmake sdl2 qt@6 libslirp libarchive libepoxy`
 3. Download the melonDS repository and prepare:
-  ```zsh
-  git clone https://github.com/Arisotura/melonDS
-  cd melonDS
-  mkdir build && cd build
-  ```
+   ```zsh
+   git clone https://github.com/Arisotura/melonDS
+   cd melonDS
+   ```
 4. Compile:
    ```zsh
-   cmake .. -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6);$(brew --prefix libarchive)" -DUSE_QT6=ON -DMACOS_BUNDLE_LIBS=ON
-   make -j$(sysctl -n hw.logicalcpu)
+   cmake -B build -DCMAKE_PREFIX_PATH="$(brew --prefix qt@6);$(brew --prefix libarchive)" -DUSE_QT6=ON
+   cmake --build build -j$(sysctl -n hw.logicalcpu)
    ```
-If everything went well, melonDS.app should now be in the current directory.
+If everything went well, melonDS.app should now be in the `build` directory.
+
+#### Self-contained app bundle
+If you want an app bundle that can be distributed to other computers without needing to install dependencies through Homebrew, you can additionally run `
+../tools/mac-bundle.rb melonDS.app` after the build is completed, or add `-DMACOS_BUNDLE_LIBS=ON` to the first CMake command.
 
-   
 ## TODO LIST
 
  * better DSi emulation
diff --git a/cmake/FixInterfaceIncludes.cmake b/cmake/FixInterfaceIncludes.cmake
new file mode 100644
index 00000000..513c1117
--- /dev/null
+++ b/cmake/FixInterfaceIncludes.cmake
@@ -0,0 +1,28 @@
+# The entire codebase quite reasonably does things like #include <SDL2/SDL.h> or <epoxy/gl.h>
+# CMake apparently doesn't think you should be doing this, so just includes $PREFIX/include/packagename for a given
+# package as include directories when using `target_link_libraries` with an imported target, this hacky function fixes
+# that up so includes can keep working as they always did but we can still use fancy imported targets.
+# This is stupid.
+
+function(fix_interface_includes)
+    foreach (target ${ARGN})
+        set(NEW_DIRS)
+        get_target_property(DIRS "${target}" INTERFACE_INCLUDE_DIRECTORIES)
+
+        if (NOT DIRS)
+            continue()
+        endif()
+
+        foreach (DIR ${DIRS})
+            get_filename_component(PARENT_DIR "${DIR}" DIRECTORY)
+
+            if (PARENT_DIR MATCHES "include$")
+                list(APPEND NEW_DIRS "${PARENT_DIR}")
+            endif()
+        endforeach()
+
+        list(APPEND DIRS ${NEW_DIRS})
+        set_target_properties("${target}" PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${DIRS}")
+    endforeach()
+endfunction()
+
diff --git a/res/melon.plist.in b/res/melon.plist.in
index 1057c474..20d385a0 100644
--- a/res/melon.plist.in
+++ b/res/melon.plist.in
@@ -13,9 +13,9 @@
     <key>CFBundlePackageType</key>
     <string>APPL</string>
     <key>CFBundleVersion</key>
-    <string>${MELONDS_VERSION}</string>
+    <string>${melonDS_VERSION}</string>
     <key>CFBundleShortVersionString</key>
-    <string>${MELONDS_VERSION}</string> 
+    <string>${melonDS_VERSION}</string> 
     <key>NSHumanReadableCopyright</key>
     <string>Licensed under GPLv3</string>
     <key>NSHighResolutionCapable</key>
diff --git a/res/melon.rc.in b/res/melon.rc.in
index 3851813c..27c7cbdf 100644
--- a/res/melon.rc.in
+++ b/res/melon.rc.in
@@ -6,8 +6,8 @@
 
 //include version information in .exe, modify these values to match your needs
 1 VERSIONINFO
-FILEVERSION ${MELONDS_VERSION_MAJOR},${MELONDS_VERSION_MINOR},${MELONDS_VERSION_PATCH},0
-PRODUCTVERSION ${MELONDS_VERSION_MAJOR},${MELONDS_VERSION_MINOR},${MELONDS_VERSION_PATCH},0
+FILEVERSION ${melonDS_VERSION_MAJOR},${melonDS_VERSION_MINOR},${melonDS_VERSION_PATCH},0
+PRODUCTVERSION ${melonDS_VERSION_MAJOR},${melonDS_VERSION_MINOR},${melonDS_VERSION_PATCH},0
 FILETYPE VFT_APP
 {
   BLOCK "StringFileInfo"
@@ -15,14 +15,14 @@ FILETYPE VFT_APP
 		BLOCK "040904E4"
 		{
 			VALUE "CompanyName", "Melon Factory of Kuribo64"
-			VALUE "FileVersion", "${MELONDS_VERSION}"
+			VALUE "FileVersion", "${melonDS_VERSION}"
 			VALUE "FileDescription", "melonDS emulator"
 			VALUE "InternalName", "SDnolem"
 			VALUE "LegalCopyright", "2016-2022 melonDS team"
 			VALUE "LegalTrademarks", ""
 			VALUE "OriginalFilename", "zafkflzdasd.exe"
 			VALUE "ProductName", "melonDS"
-			VALUE "ProductVersion", "${MELONDS_VERSION}"
+			VALUE "ProductVersion", "${melonDS_VERSION}"
 		}
 	}
   BLOCK "VarFileInfo"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7288b540..cdb05871 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,141 +1,145 @@
-project(core)
-
 set (CMAKE_CXX_STANDARD 17)
 
-add_library(core STATIC
-	ARCodeFile.cpp
-	AREngine.cpp
-	ARM.cpp
-	ARM_InstrTable.h
-	ARMInterpreter.cpp
-	ARMInterpreter_ALU.cpp
-	ARMInterpreter_Branch.cpp
-	ARMInterpreter_LoadStore.cpp
-	CP15.cpp
-	CRC32.cpp
-	DMA.cpp
-	DMA_Timings.h
-	DSi.cpp
-	DSi_AES.cpp
-	DSi_Camera.cpp
-	DSi_DSP.cpp
-	DSi_I2C.cpp
-	DSi_NAND.cpp
-	DSi_NDMA.cpp
-	DSi_NWifi.cpp
-	DSi_SD.cpp
-	DSi_SPI_TSC.cpp
-	FATStorage.cpp
-	FIFO.h
-	GBACart.cpp
-	GPU.cpp
-	GPU2D.cpp
-	GPU2D_Soft.cpp
-	GPU3D.cpp
-	GPU3D_Soft.cpp
-	melonDLDI.h
-	NDS.cpp
-	NDSCart.cpp
-	Platform.h
-	ROMList.h
-	FreeBIOS.h
-	RTC.cpp
-	Savestate.cpp
-	SPI.cpp
-	SPU.cpp
-	types.h
-	version.h
-	Wifi.cpp
-	WifiAP.cpp
+include(FixInterfaceIncludes)
 
-	fatfs/diskio.c
-	fatfs/ff.c
-	fatfs/ffsystem.c
-	fatfs/ffunicode.c
-	fatfs/ffconf.h
-	
-	sha1/sha1.c
-	tiny-AES-c/aes.c
-	xxhash/xxhash.c
-)
+add_library(core STATIC
+    ARCodeFile.cpp
+    AREngine.cpp
+    ARM.cpp
+    ARM_InstrTable.h
+    ARMInterpreter.cpp
+    ARMInterpreter_ALU.cpp
+    ARMInterpreter_Branch.cpp
+    ARMInterpreter_LoadStore.cpp
+    CP15.cpp
+    CRC32.cpp
+    DMA.cpp
+    DMA_Timings.h
+    DSi.cpp
+    DSi_AES.cpp
+    DSi_Camera.cpp
+    DSi_DSP.cpp
+    DSi_I2C.cpp
+    DSi_NAND.cpp
+    DSi_NDMA.cpp
+    DSi_NWifi.cpp
+    DSi_SD.cpp
+    DSi_SPI_TSC.cpp
+    FATStorage.cpp
+    FIFO.h
+    GBACart.cpp
+    GPU.cpp
+    GPU2D.cpp
+    GPU2D_Soft.cpp
+    GPU3D.cpp
+    GPU3D_Soft.cpp
+    melonDLDI.h
+    NDS.cpp
+    NDSCart.cpp
+    Platform.h
+    ROMList.h
+    FreeBIOS.h
+    RTC.cpp
+    Savestate.cpp
+    SPI.cpp
+    SPU.cpp
+    types.h
+    version.h
+    Wifi.cpp
+    WifiAP.cpp
+
+    fatfs/diskio.c
+    fatfs/ff.c
+    fatfs/ffsystem.c
+    fatfs/ffunicode.c
+    fatfs/ffconf.h
+
+    sha1/sha1.c
+    tiny-AES-c/aes.c
+    xxhash/xxhash.c)
 
 if (ENABLE_OGLRENDERER)
-	target_sources(core PRIVATE
-		GPU_OpenGL.cpp
-		GPU_OpenGL_shaders.h
-		GPU3D_OpenGL.cpp
-		GPU3D_OpenGL_shaders.h
-		OpenGLSupport.cpp
-	)
+    target_sources(core PRIVATE
+        GPU_OpenGL.cpp
+        GPU_OpenGL_shaders.h
+        GPU3D_OpenGL.cpp
+        GPU3D_OpenGL_shaders.h
+        OpenGLSupport.cpp)
 endif()
 
 if (ENABLE_JIT)
-	enable_language(ASM)
+    enable_language(ASM)
 
-	target_sources(core PRIVATE
-		ARM_InstrInfo.cpp
+    target_sources(core PRIVATE
+        ARM_InstrInfo.cpp
 
-		ARMJIT.cpp
-		ARMJIT_Memory.cpp
+        ARMJIT.cpp
+        ARMJIT_Memory.cpp
 
-		dolphin/CommonFuncs.cpp
-	)
+        dolphin/CommonFuncs.cpp)
 
-	if (ARCHITECTURE STREQUAL x86_64)
-		target_sources(core PRIVATE
-			dolphin/x64ABI.cpp
-			dolphin/x64CPUDetect.cpp
-			dolphin/x64Emitter.cpp
+    if (ARCHITECTURE STREQUAL x86_64)
+        target_sources(core PRIVATE
+            dolphin/x64ABI.cpp
+            dolphin/x64CPUDetect.cpp
+            dolphin/x64Emitter.cpp
 
-			ARMJIT_x64/ARMJIT_Compiler.cpp
-			ARMJIT_x64/ARMJIT_ALU.cpp
-			ARMJIT_x64/ARMJIT_LoadStore.cpp
-			ARMJIT_x64/ARMJIT_Branch.cpp
+            ARMJIT_x64/ARMJIT_Compiler.cpp
+            ARMJIT_x64/ARMJIT_ALU.cpp
+            ARMJIT_x64/ARMJIT_LoadStore.cpp
+            ARMJIT_x64/ARMJIT_Branch.cpp
 
-			ARMJIT_x64/ARMJIT_Linkage.S
-		)
-	endif()
-	if (ARCHITECTURE STREQUAL ARM64)
-		target_sources(core PRIVATE
-			dolphin/Arm64Emitter.cpp
-			dolphin/MathUtil.cpp
+            ARMJIT_x64/ARMJIT_Linkage.S)
+    endif()
+    if (ARCHITECTURE STREQUAL ARM64)
+        target_sources(core PRIVATE
+            dolphin/Arm64Emitter.cpp
+            dolphin/MathUtil.cpp
 
-			ARMJIT_A64/ARMJIT_Compiler.cpp
-			ARMJIT_A64/ARMJIT_ALU.cpp
-			ARMJIT_A64/ARMJIT_LoadStore.cpp
-			ARMJIT_A64/ARMJIT_Branch.cpp
+            ARMJIT_A64/ARMJIT_Compiler.cpp
+            ARMJIT_A64/ARMJIT_ALU.cpp
+            ARMJIT_A64/ARMJIT_LoadStore.cpp
+            ARMJIT_A64/ARMJIT_Branch.cpp
 
-			ARMJIT_A64/ARMJIT_Linkage.S
-		)
-	endif()
+            ARMJIT_A64/ARMJIT_Linkage.S)
+    endif()
 endif()
 
 add_subdirectory(teakra EXCLUDE_FROM_ALL)
-target_link_libraries(core teakra)
+target_link_libraries(core PRIVATE teakra)
 
+find_library(m MATH_LIBRARY)
+
+if (MATH_LIBRARY)
+    target_link_libraries(core PRIVATE ${MATH_LIBRARY})
+endif()
 
 if (ENABLE_OGLRENDERER)
     find_package(PkgConfig REQUIRED)
-    pkg_check_modules(EPOXY REQUIRED epoxy)
+    pkg_check_modules(Epoxy REQUIRED IMPORTED_TARGET epoxy)
+    fix_interface_includes(PkgConfig::Epoxy)
 
-    target_include_directories(core PRIVATE ${EPOXY_INCLUDE_DIRS})
-    if (WIN32)
-        target_link_libraries(core ole32 comctl32 ws2_32 ${EPOXY_LIBRARIES})
-    elseif (APPLE)
-        target_link_libraries(core ${EPOXY_LIBRARIES})
-    else()
-        target_link_libraries(core rt ${EPOXY_LIBRARIES})
+    target_link_libraries(core PUBLIC PkgConfig::Epoxy)
+
+    target_compile_definitions(core PUBLIC OGLRENDERER_ENABLED)
+endif()
+
+if (ENABLE_JIT)
+    target_compile_definitions(core PUBLIC JIT_ENABLED)
+
+
+    if (ENABLE_JIT_PROFILING)
+        include(cmake/FindVTune.cmake)
+        add_definitions(-DJIT_PROFILING_ENABLED)
     endif()
-else()
-	if (WIN32)
-		target_link_libraries(core ole32 comctl32 ws2_32)
-	elseif (APPLE)
-		target_link_libraries(core)
-	else()
-		target_link_libraries(core rt)
-	endif()
+endif()
+
+if (WIN32)
+    target_link_libraries(core PRIVATE ole32 comctl32 ws2_32)
+elseif(NOT APPLE)
+    target_link_libraries(core PRIVATE rt)
 endif()
 
 if (ENABLE_JIT_PROFILING)
-	target_link_libraries(core jitprofiling)
+    target_link_libraries(core PRIVATE jitprofiling)
 endif()
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index ec88026f..6f95cc54 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -1,10 +1,12 @@
-project(qt_sdl)
+include(CMakeDependentOption)
 
-SET(SOURCES_QT_SDL
+include(FixInterfaceIncludes)
+
+set(SOURCES_QT_SDL
     main.cpp
     main_shaders.h
     CheatsDialog.cpp
-	Config.cpp
+    Config.cpp
     EmuSettingsDialog.cpp
     PowerManagement/PowerManagementDialog.cpp
     PowerManagement/resources/battery.qrc
@@ -28,9 +30,9 @@ SET(SOURCES_QT_SDL
     font.h
     Platform.cpp
     QPathInput.h
-	ROMManager.cpp
-	SaveManager.cpp
-    
+    ROMManager.cpp
+    SaveManager.cpp
+
     ArchiveUtil.h
     ArchiveUtil.cpp
 
@@ -40,7 +42,7 @@ SET(SOURCES_QT_SDL
     ../mic_blow.h
 
     ${CMAKE_SOURCE_DIR}/res/melon.qrc
-)
+    )
 
 if (APPLE)
     option(USE_QT6 "Build using Qt 6 instead of 5" ON)
@@ -54,27 +56,9 @@ if (WIN32)
 endif()
 
 if (USE_QT6)
-    if (BUILD_STATIC AND QT6_STATIC_DIR)
-        set(QT6_STATIC_BASE ${QT6_STATIC_DIR}/lib/cmake/Qt6)
-        set(Qt6_DIR ${QT6_STATIC_BASE})
-        set(Qt6Core_DIR ${QT6_STATIC_BASE}Core)
-        set(Qt6Gui_DIR ${QT6_STATIC_BASE}Gui)
-        set(Qt6Widgets_DIR ${QT6_STATIC_BASE}Widgets)
-        set(Qt6Network_DIR ${QT6_STATIC_BASE}Network)
-        set(Qt6OpenGL_DIR ${QT6_STATIC_BASE}OpenGL)
-        set(Qt6OpenGLWidgets_DIR ${QT6_STATIC_BASE}OpenGLWidgets)
-    endif()
     find_package(Qt6 COMPONENTS Core Gui Widgets Network OpenGL OpenGLWidgets REQUIRED)
     set(QT_LINK_LIBS Qt6::Core Qt6::Gui Qt6::Widgets Qt6::Network Qt6::OpenGL Qt6::OpenGLWidgets)
 else()
-    if (BUILD_STATIC AND QT5_STATIC_DIR)
-        set(QT5_STATIC_BASE ${QT5_STATIC_DIR}/lib/cmake/Qt5)
-        set(Qt5_DIR ${QT5_STATIC_BASE})
-        set(Qt5Core_DIR ${QT5_STATIC_BASE}Core)
-        set(Qt5Gui_DIR ${QT5_STATIC_BASE}Gui)
-        set(Qt5Widgets_DIR ${QT5_STATIC_BASE}Widgets)
-        set(Qt5Network_DIR ${QT5_STATIC_BASE}Network)
-    endif()
     find_package(Qt5 COMPONENTS Core Gui Widgets Network REQUIRED)
     set(QT_LINK_LIBS Qt5::Core Qt5::Gui Qt5::Widgets Qt5::Network)
 endif()
@@ -83,63 +67,48 @@ set(CMAKE_AUTOMOC ON)
 set(CMAKE_AUTOUIC ON)
 set(CMAKE_AUTORCC ON)
 
-find_package(Threads REQUIRED)
-find_package(PkgConfig REQUIRED)
-find_package(Iconv REQUIRED)
-pkg_check_modules(SDL2 REQUIRED sdl2)
-pkg_check_modules(SLIRP REQUIRED slirp)
-pkg_check_modules(LIBARCHIVE REQUIRED libarchive)
-add_compile_definitions(ARCHIVE_SUPPORT_ENABLED)
-
-if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release))
-    add_executable(melonDS WIN32 ${SOURCES_QT_SDL})
-else()
-    add_executable(melonDS ${SOURCES_QT_SDL})
+if (BUILD_STATIC)
+    list(APPEND PKG_CONFIG_EXECUTABLE "--static")
 endif()
 
-target_link_libraries(melonDS ${CMAKE_THREAD_LIBS_INIT})
+find_package(Threads REQUIRED)
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(SDL2 REQUIRED IMPORTED_TARGET sdl2)
+pkg_check_modules(Slirp REQUIRED IMPORTED_TARGET slirp)
+pkg_check_modules(LibArchive REQUIRED IMPORTED_TARGET libarchive)
 
-target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS} ${SDL2_PREFIX}/include ${SLIRP_INCLUDE_DIRS} ${LIBARCHIVE_INCLUDE_DIRS})
-target_link_directories(melonDS PRIVATE ${SDL2_LIBRARY_DIRS} ${SLIRP_LIBRARY_DIRS})
-target_link_directories(melonDS PRIVATE ${LIBARCHIVE_LIBRARY_DIRS})
+fix_interface_includes(PkgConfig::SDL2 PkgConfig::Slirp PkgConfig::LibArchive)
+
+add_compile_definitions(ARCHIVE_SUPPORT_ENABLED)
+
+add_executable(melonDS ${SOURCES_QT_SDL})
+
+if (BUILD_STATIC)
+    qt_import_plugins(melonDS INCLUDE Qt::QSvgPlugin)
+    target_link_options(melonDS PRIVATE -static)
+endif()
 
 target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
 target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
 target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..")
-target_link_libraries(melonDS core)
-
-if (BUILD_STATIC)
-    target_link_libraries(melonDS -static ${SDL2_STATIC_LIBRARIES} ${SLIRP_STATIC_LIBRARIES} ${LIBARCHIVE_STATIC_LIBRARIES})
-    qt_import_plugins(melonDS INCLUDE Qt::QSvgPlugin)
-else()
-    target_link_libraries(melonDS ${SDL2_LIBRARIES} ${SLIRP_LIBRARIES} ${LIBARCHIVE_LIBRARIES})
-endif()
-
-if (NOT Iconv_IS_BUILT_IN)
-    target_link_libraries(melonDS ${Iconv_LIBRARIES})
-endif()
+target_link_libraries(melonDS PRIVATE core)
+target_link_libraries(melonDS PRIVATE PkgConfig::SDL2 PkgConfig::Slirp PkgConfig::LibArchive)
+target_link_libraries(melonDS PRIVATE ${QT_LINK_LIBS} ${CMAKE_DL_LIBS})
 
 if (UNIX)
     option(PORTABLE "Make a portable build that looks for its configuration in the current directory" OFF)
-    target_link_libraries(melonDS ${QT_LINK_LIBS})
-    if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
-        target_link_libraries(melonDS dl)
-    endif()
 elseif (WIN32)
     option(PORTABLE "Make a portable build that looks for its configuration in the current directory" ON)
+
     configure_file("${CMAKE_SOURCE_DIR}/res/melon.rc.in" "${CMAKE_SOURCE_DIR}/melon.rc")
     target_sources(melonDS PUBLIC "${CMAKE_SOURCE_DIR}/melon.rc")
 
-    target_link_libraries(melonDS comctl32 d2d1 dwrite uxtheme ws2_32 iphlpapi gdi32)
-    if (BUILD_STATIC)
-        target_link_libraries(melonDS imm32 winmm version setupapi -static z zstd ${QT_LINK_LIBS})
-    else()
-        target_link_libraries(melonDS ${QT_LINK_LIBS})
-    endif()
+    target_link_libraries(melonDS PRIVATE ws2_32 iphlpapi)
+    set_target_properties(melonDS PROPERTIES WIN32_EXECUTABLE $<CONFIG:Release>)
 endif()
 
 if (PORTABLE)
-    add_definitions(-DPORTABLE)
+    target_compile_definitions(melonDS PRIVATE PORTABLE)
 endif()
 
 if (APPLE)
@@ -152,7 +121,7 @@ if (APPLE)
         MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/res/melon.plist.in
         OUTPUT_NAME melonDS
         RESOURCE "${RESOURCE_FILES}")
-	
+
 
     option(MACOS_BUNDLE_LIBS "Bundle libraries with the app on macOS" OFF)
     option(MACOS_BUILD_DMG "Build DMG image of the macOS application bundle" OFF)
@@ -170,8 +139,8 @@ endif()
 if (UNIX AND NOT APPLE)
     foreach(SIZE 16 32 48 64 128 256)
         install(FILES ${CMAKE_SOURCE_DIR}/res/icon/melon_${SIZE}x${SIZE}.png
-                DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${SIZE}x${SIZE}/apps
-                RENAME net.kuribo64.melonDS.png)
+            DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/${SIZE}x${SIZE}/apps
+            RENAME net.kuribo64.melonDS.png)
     endforeach()
 
     install(FILES ${CMAKE_SOURCE_DIR}/res/net.kuribo64.melonDS.desktop DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)