shithub: candycrisis

Download patch

ref: 8871dfafcd58c3952762d5f0de3a6222e638fba2
parent: 2c8cf7b0808ec297335d7645ccee724d3363a0a8
author: Iliyas Jorio <[email protected]>
date: Sun Jan 8 12:54:32 EST 2023

Simplify CMakeLists.txt - Static build of SDL by default

diff: cannot open a/cmake//null: file does not exist: 'a/cmake//null'
--- a/.github/workflows/CompileCheck.yml
+++ /dev/null
@@ -1,32 +1,0 @@
-name: Full Compile Check
-
-on: [workflow_dispatch, push]
-
-jobs:
-  full-compile-check:
-    name: ${{ matrix.platform.name }}
-    runs-on: ${{ matrix.platform.os }}
-
-    strategy:
-      fail-fast: false
-      matrix:
-        platform:
-          - { name: Linux/GCC (ancient), os: ubuntu-18.04, extraflags: "--system-sdl" }
-          - { name: Linux/GCC, os: ubuntu-latest, extraflags: "--system-sdl" }
-          - { name: Linux/Clang, os: ubuntu-latest, extraflags: "--system-sdl" }
-          - { name: Windows/VS2022, os: windows-2022, extraflags: "-G 'Visual Studio 17 2022'" }
-          - { name: Windows/VS2019, os: windows-2019, extraflags: "-G 'Visual Studio 16 2019'" }
-          - { name: Mac, os: macos-11 }
-
-    steps:
-      - name: Install Linux build dependencies
-        if: runner.os == 'Linux'
-        run: |
-          sudo apt update
-          sudo apt install libsdl2-dev
-
-      - uses: actions/checkout@v2
-        with:
-          submodules: 'recursive'
-          
-      - run: python3 build.py --dependencies --configure --build ${{ matrix.platform.extraflags }}
--- a/.github/workflows/ReleaseBuilds.yml
+++ /dev/null
@@ -1,80 +1,0 @@
-name: Make Release Builds
-
-on: [workflow_dispatch]
-
-jobs:
-  build-linux-appimage:
-    runs-on: ubuntu-18.04
-    steps:
-      - uses: actions/checkout@v2  # Checks out repository under $GITHUB_WORKSPACE so the job can access it
-        with:
-          submodules: 'recursive'
-      - name: Get artifact name
-        run: |
-          echo "GAME_ARTIFACT=$(python3 build.py --print-artifact-name)" >> $GITHUB_ENV
-          echo $GAME_ARTIFACT
-      - name: Get build dependencies for SDL from APT  # cf. https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md
-        run: |
-          sudo apt update
-          sudo apt install libasound2-dev libpulse-dev libaudio-dev libjack-dev libx11-dev libxext-dev libxrandr-dev libxcursor-dev libxi-dev libxinerama-dev libxxf86vm-dev libxss-dev libgl1-mesa-dev libdbus-1-dev libudev-dev libgles2-mesa-dev libegl1-mesa-dev libibus-1.0-dev fcitx-libs-dev libsamplerate0-dev libsndio-dev libwayland-dev libxkbcommon-dev libdrm-dev libgbm-dev
-      - run: python3 build.py --dependencies
-      - run: python3 build.py --configure
-      - run: python3 build.py --build
-      - run: python3 build.py --package
-      - uses: actions/upload-artifact@v2
-        with:
-          name: ${{ env.GAME_ARTIFACT }}
-          path: dist/${{ env.GAME_ARTIFACT }}
-
-  build-windows:
-    runs-on: windows-2022
-    steps:
-      - uses: actions/checkout@v2
-        with:
-          submodules: 'recursive'
-      - name: Get artifact name
-        run: |
-          echo ("GAME_ARTIFACT=" + (python3 build.py --print-artifact-name)) >> $env:GITHUB_ENV
-          echo $env:GAME_ARTIFACT
-      - run: python3 build.py --dependencies
-      - run: python3 build.py --configure -G 'Visual Studio 17 2022'
-      - run: python3 build.py --build
-      - run: python3 build.py --package
-      - uses: actions/upload-artifact@v2
-        with:
-          name: ${{ env.GAME_ARTIFACT }}
-          path: dist/${{ env.GAME_ARTIFACT }}
-
-  build-macos:
-    runs-on: macos-11
-    env:
-      CODE_SIGN_IDENTITY: ${{ secrets.APPLE_CODE_SIGN_IDENTITY }}
-    steps:
-      - uses: apple-actions/import-codesign-certs@v1
-        with:
-          p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
-          p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
-      - name: Install gon for notarization
-        run: |
-          brew tap mitchellh/gon
-          brew install mitchellh/gon/gon
-      - uses: actions/checkout@v2
-        with:
-          submodules: 'recursive'
-      - name: Get artifact name
-        run: |
-          echo "GAME_ARTIFACT=$(python3 build.py --print-artifact-name)" >> $GITHUB_ENV
-          echo $GAME_ARTIFACT
-      - run: python3 build.py --dependencies
-      - run: python3 build.py --configure
-      - run: python3 build.py --build
-      - run: python3 build.py --package
-      - name: Notarize
-        run: gon packaging/gon-config.json
-        env:
-          AC_USERNAME: ${{ secrets.APPLE_NOTARIZATION_USERNAME }}
-          AC_PASSWORD: ${{ secrets.APPLE_NOTARIZATION_PASSWORD }}
-      - uses: actions/upload-artifact@v2
-        with:
-          name: ${{ env.GAME_ARTIFACT }}
-          path: dist/${{ env.GAME_ARTIFACT }}
--- /dev/null
+++ b/.github/workflows/release-aarch64.yml
@@ -1,0 +1,84 @@
+name: Make Release Builds (linux/aarch64)
+
+on: [workflow_dispatch]
+
+jobs:
+  build-linux-appimage-aarch64:
+    runs-on: ubuntu-20.04
+    timeout-minutes: 100  # this job may take up to an hour
+
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          submodules: 'recursive'
+
+      # Create shared directory ON HOST. (If it's done within qemu, it'll be created with root permissions)
+      - name: Create artifacts directory shared with docker
+        run: |
+          mkdir -p "artifacts"
+
+      # QEMU can't run appimagetool-aarch64, so we have to build the AppImage on x86_64
+      - name: Download appimagetool
+        run : |
+          pushd artifacts
+          wget -q https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage
+          wget -q https://github.com/AppImage/AppImageKit/releases/download/13/runtime-aarch64
+          chmod +x appimagetool-x86_64.AppImage
+          chmod +x runtime-aarch64
+          popd
+
+      - uses: uraimo/run-on-arch-action@v2
+        name: Build game via QEMU
+        id: buildgame
+        with:
+          arch: aarch64
+
+          # Distro must be kept in sync with `runs-on` above.
+          # See: https://github.com/uraimo/run-on-arch-action#supported-platforms
+          distro: ubuntu20.04
+
+          # (Optional) Speeds up builds by storing container images in a GitHub package registry.
+          githubToken: ${{ github.token }}
+
+          # Mount the artifacts directory as /artifacts in the container
+          dockerRunArgs: |
+            --volume "${PWD}/artifacts:/artifacts"
+
+          # Install build tools for the game and SDL build dependencies.
+          # See: https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md (last updated for SDL 2.26.0)
+          install: |
+            apt update -y
+            apt install -y build-essential cmake
+            #apt install -y libsdl2-dev  #----- for quick testing
+            apt install -y libasound2-dev libpulse-dev \
+              libaudio-dev libjack-dev libsndio-dev libsamplerate0-dev libx11-dev libxext-dev \
+              libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libwayland-dev \
+              libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
+              libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
+
+          # Build the aarch64 version under dist/, then tar it up and move it to /artifacts.
+          # (We're not building directly in /artifacts as this would cause permission issues when moving back to the x86_64 host)
+          run: |
+            cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
+            cmake --build build
+            bash packaging/prepare_appimage_appdir.sh build/CandyCrisis
+            cd build
+            tar cvf /artifacts/aarch64-dist.tar ./*.AppDir
+
+      # QEMU can't run appimagetool-aarch64, so we have to build the AppImage on x86_64
+      - name: Create AppImage on x86_64 host
+        run: |
+          cd artifacts
+          tar xvf aarch64-dist.tar
+
+          APPIMAGE_INPUT=$(ls -d --indicator-style=none *.AppDir)
+          APPIMAGE_OUTPUT=${APPIMAGE_INPUT%.AppDir}.AppImage
+          echo "APPIMAGE_OUTPUT=$APPIMAGE_OUTPUT" >> $GITHUB_ENV
+
+          ./appimagetool-x86_64.AppImage -v --runtime-file runtime-aarch64 --no-appstream $APPIMAGE_INPUT $APPIMAGE_OUTPUT
+
+      - name: Upload
+        uses: actions/upload-artifact@v3
+        with:
+          name: ${{ env.APPIMAGE_OUTPUT }}
+          path: artifacts/${{ env.APPIMAGE_OUTPUT }}
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -1,0 +1,127 @@
+name: Make Release Builds
+
+on: [workflow_dispatch]
+
+jobs:
+  build-linux-appimage:
+    runs-on: ubuntu-20.04  # Use oldest distro still supported by GitHub to cover the oldest possible glibc
+    timeout-minutes: 20
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3  # Checks out repository under $GITHUB_WORKSPACE so the job can access it
+        with:
+          submodules: 'recursive'
+
+      - name: Get CPU count
+        run: |
+          NPROC=$(python3 -c 'import multiprocessing; print(multiprocessing.cpu_count())')
+          echo "NPROC=$NPROC" >> $GITHUB_ENV
+          echo CPU count = $NPROC
+
+      - name: Get build dependencies for SDL from APT  # cf. https://github.com/libsdl-org/SDL/blob/main/docs/README-linux.md
+        run: |
+          sudo apt update
+          sudo apt install -y libasound2-dev libpulse-dev \
+            libaudio-dev libjack-dev libsndio-dev libsamplerate0-dev libx11-dev libxext-dev \
+            libxrandr-dev libxcursor-dev libxfixes-dev libxi-dev libxss-dev libwayland-dev \
+            libxkbcommon-dev libdrm-dev libgbm-dev libgl1-mesa-dev libgles2-mesa-dev \
+            libegl1-mesa-dev libdbus-1-dev libibus-1.0-dev libudev-dev fcitx-libs-dev
+
+      - name: Configure
+        run: cmake -S . -B build -DCMAKE_BUILD_TYPE=RelWithDebInfo
+
+      - name: Build
+        run: cmake --build build -- -j ${{ env.NPROC }}
+
+      - name: Prepare AppDir
+        run: bash packaging/prepare_appimage_appdir.sh build/CandyCrisis
+
+      - name: Make AppImage
+        run: |
+          wget https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage
+          chmod +x appimagetool-x86_64.AppImage
+          ./appimagetool-x86_64.AppImage --no-appstream build/CandyCrisis.AppDir build/CandyCrisis.AppImage
+
+      - name: Upload
+        uses: actions/upload-artifact@v3
+        with:
+          name: linux-build
+          path: build/CandyCrisis.AppImage
+          
+  build-windows:
+    runs-on: windows-2022
+    timeout-minutes: 20
+
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+        with:
+          submodules: 'recursive'
+          
+      - name: Configure
+        run: cmake -S . -B build -G 'Visual Studio 17 2022'
+
+      - name: Build
+        run: cmake --build build --config Release -- -m
+
+      - name: Copy vcredist
+        run: |
+          cmake --install build --prefix build/install
+          copy build/install/bin/msvcp140.dll build/Release
+          copy build/install/bin/vcruntime140.dll build/Release
+          copy build/install/bin/vcruntime140_1.dll build/Release
+
+      - name: Upload
+        uses: actions/upload-artifact@v3
+        with:
+          name: windows-build
+          path: build/Release
+
+  build-macos:
+    runs-on: macos-11
+    timeout-minutes: 20
+
+    steps:
+      - name: Import codesigning certs
+        uses: apple-actions/import-codesign-certs@v1
+        with:
+          p12-file-base64: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_P12_BASE64 }}
+          p12-password: ${{ secrets.APPLE_DEVELOPER_CERTIFICATE_PASSWORD }}
+
+      - name: Get CPU count
+        run: |
+          NPROC=$(python3 -c 'import multiprocessing; print(multiprocessing.cpu_count())')
+          echo "NPROC=$NPROC" >> $GITHUB_ENV
+          echo CPU count = $NPROC
+
+      - name: Checkout
+        uses: actions/checkout@v3
+        with:
+          submodules: 'recursive'
+
+      - name: Configure
+        run: cmake -S . -B build -G Xcode
+
+      - name: Build
+        run: cmake --build build --config RelWithDebInfo -- -j ${{ env.NPROC }}
+
+      - name: Codesign
+        run: codesign --force --sign ${{ secrets.APPLE_DEVELOPMENT_TEAM }} --options runtime build/RelWithDebInfo/CandyCrisis.app
+      
+      - name: Create dmg
+        run: hdiutil create -fs HFS+ -srcfolder build/RelWithDebInfo -volname "Candy Crisis" build/game.dmg
+
+      - name: Notarize
+        run: |
+          xcrun notarytool store-credentials MyNotarizationProfileName --apple-id ${{ secrets.APPLE_NOTARIZATION_USERNAME }} --password ${{ secrets.APPLE_NOTARIZATION_PASSWORD }} --team-id ${{ secrets.APPLE_DEVELOPMENT_TEAM }}
+          xcrun notarytool submit build/game.dmg --keychain-profile MyNotarizationProfileName --wait
+
+      - name: Staple
+        run: xcrun stapler staple build/game.dmg
+
+      - name: Upload
+        uses: actions/upload-artifact@v3
+        with:
+          name: mac-build
+          path: build/game.dmg
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
-build-*/
-cache/
-cmake-build-*/
-dist/
-extern/
+/build*
+/cache
+/cmake-build*
+/dist
+/extern
+
+.DS_Store
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,148 +1,81 @@
-cmake_minimum_required(VERSION 3.13)
+cmake_minimum_required(VERSION 3.16)
 
-set(GAME_TARGET				"CandyCrisis")
-set(GAME_VERSION			"3.0.0")
-set(GAME_MAC_ICNS			"packaging/${GAME_TARGET}.icns")
-set(GAME_MAC_COPYRIGHT		"https://github.com/jorio/candycrisis")
-set(GAME_MAC_BUNDLE_ID		"io.jor.candycrisis")
+set(GAME_TARGET "CandyCrisis")
+set(GAME_MAC_BUNDLE_ID "io.jor.candycrisis")
 
-set(CMAKE_MODULE_PATH		"${CMAKE_SOURCE_DIR}/cmake")
-set(CMAKE_C_STANDARD		17)
-set(CMAKE_CXX_STANDARD		17)
-
-set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum OS X deployment version")
+set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum macOS deployment version")
 set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "Target macOS architectures")
 
-project(${GAME_TARGET}
-	VERSION ${GAME_VERSION}
-	LANGUAGES C CXX
-)
+set(CMAKE_CXX_STANDARD 20)
+if (${CMAKE_VERSION} VERSION_LESS "3.21")
+	set(CMAKE_C_STANDARD	11)
+else()
+	set(CMAKE_C_STANDARD	17)
+endif()
 
-#------------------------------------------------------------------------------
-# GLOBAL OPTIONS (BEFORE ADDING SUBDIRECTORIES)
-#------------------------------------------------------------------------------
+project(
+	${GAME_TARGET} LANGUAGES C CXX
+	VERSION 3.0.0
+	)
 
-if(MSVC)
-	add_compile_definitions(UNICODE _UNICODE)
 
-	set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${GAME_TARGET})
-endif()
 
-#------------------------------------------------------------------------------
-# DEPENDENCIES
-#------------------------------------------------------------------------------
+# Create an option to switch between a system sdl library and a vendored sdl library
+option(SYSTEM_SDL "Use system SDL" OFF)
 
-find_package(SDL2 REQUIRED COMPONENTS main)
+# Set Visual Studio startup project
+set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${GAME_TARGET})
 
+set(GAME_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
 #------------------------------------------------------------------------------
-# GAME SOURCES
+# FIND SDL
 #------------------------------------------------------------------------------
 
-set(GAME_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
+if(SYSTEM_SDL)
+	# 1. Look for an SDL2 package, 2. look for the SDL2 component and 3. fail if none can be found
+	find_package(SDL2 REQUIRED CONFIG REQUIRED COMPONENTS SDL2)
+	
+	# 1. Look for an SDL2 package, 2. Look for the SDL2maincomponent and 3. DO NOT fail when SDL2main is not available 
+	find_package(SDL2 REQUIRED CONFIG COMPONENTS SDL2main)
+else()
+	add_subdirectory(SDL EXCLUDE_FROM_ALL)
+endif()
 
-# Write header file containing version info
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.h.in ${GAME_SRCDIR}/version.h)
-
-file(GLOB_RECURSE GAME_SOURCES CONFIGURE_DEPENDS ${GAME_SRCDIR}/*.c ${GAME_SRCDIR}/*.cpp)
-
-file(GLOB_RECURSE GAME_HEADERS CONFIGURE_DEPENDS ${GAME_SRCDIR}/*.h)
-
-set(GAME_ALL_SOURCES
-	${GAME_SOURCES}
-	${GAME_HEADERS}
-)
-
 #------------------------------------------------------------------------------
-# SOURCE GROUPS
+# GENERATED FILES
 #------------------------------------------------------------------------------
 
-source_group(TREE ${GAME_SRCDIR} PREFIX "" FILES ${GAME_ALL_SOURCES})
+# Write header file containing version info
+configure_file(${GAME_SOURCE_DIR}/version.h.in ${GAME_SOURCE_DIR}/version.h)
 
 #------------------------------------------------------------------------------
 # EXECUTABLE TARGET
 #------------------------------------------------------------------------------
 
-set(GAME_LIBRARIES ${SDL2_LIBRARIES})
 
+file(GLOB_RECURSE GAME_SOURCES CONFIGURE_DEPENDS ${GAME_SOURCE_DIR}/*.cpp ${GAME_SOURCE_DIR}/*.c ${GAME_SOURCE_DIR}/*.h)
+
 if(WIN32)
-	# "WIN32" here is equivalent to /SUBSYSTEM:WINDOWS for MSVC
-	add_executable(${GAME_TARGET} WIN32
-		${GAME_ALL_SOURCES}
-		"${CMAKE_CURRENT_SOURCE_DIR}/packaging/${GAME_TARGET}.exe.rc"
-	)
+	list(APPEND GAME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/app.exe.rc)
+
+	add_executable(${GAME_TARGET} WIN32 MACOSX_BUNDLE ${GAME_SOURCES})
 elseif(APPLE)
-	add_executable(${GAME_TARGET} MACOSX_BUNDLE
-		${GAME_ALL_SOURCES}
-		${GAME_MAC_ICNS}
-		${SDL2_LIBRARIES}
-	)
+	list(APPEND GAME_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/app.icns)
+	set_source_files_properties(${CMAKE_CURRENT_SOURCE_DIR}/packaging/app.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
+
+	add_executable(${GAME_TARGET} MACOSX_BUNDLE ${GAME_SOURCES})
 else()
 	# Math lib, explicitly required on some Linux systems
-	list(APPEND GAME_LIBRARIES m)
+	#list(APPEND GAME_LIBRARIES m)
 
-	add_executable(${GAME_TARGET} ${GAME_ALL_SOURCES})
+	add_executable(${GAME_TARGET} ${GAME_SOURCES})
 endif()
 
-target_include_directories(${GAME_TARGET} PRIVATE
-	${SDL2_INCLUDE_DIRS}
-	${GAME_SRCDIR}
-)
+target_include_directories(${GAME_TARGET} PRIVATE ${GAME_SOURCE_DIR})
 
-target_link_libraries(${GAME_TARGET} ${GAME_LIBRARIES})
 
-#------------------------------------------------------------------------------
-# DEFINES
-#------------------------------------------------------------------------------
 
-add_compile_definitions(
-	"$<$<CONFIG:DEBUG>:_DEBUG>"
-)
-
-if(WIN32)
-	target_compile_definitions(${GAME_TARGET} PRIVATE
-		WIN32_LEAN_AND_MEAN
-		_CRT_SECURE_NO_WARNINGS  # quit whining about snprintf_s
-	)
-endif()
-
-#------------------------------------------------------------------------------
-# COMPILER OPTIONS
-#------------------------------------------------------------------------------
-
-if(NOT MSVC)
-	target_compile_options(${GAME_TARGET} PRIVATE
-		-Wall
-		#-Wextra  # TODO
-		#-Wshadow  # TODO
-		-Wno-multichar
-		-Wno-unknown-pragmas
-		-Werror=return-type
-	)
-else()
-	# By default, MSVC may add /EHsc to CMAKE_CXX_FLAGS, which we don't want (we use /EHs below)
-	string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
-
-	# By default, MSVC may add /W3 to CMAKE_CXX_FLAGS, which we don't want (we use /W4 below)
-	# Note that this is not required with "cmake_minimum_required(VERSION 3.15)" or later
-	string(REPLACE "/W3" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
-	string(REPLACE "/W3" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
-
-	target_compile_options(${GAME_TARGET} PRIVATE
-		/EHs	# synchronous exceptions; also, extern "C" functions may throw exceptions
-		/W4
-		/wd4068 # ignore unrecognized pragmas
-		/wd4100 # unreferenced formal parameters
-		/wd4201 # nonstandard extension (nameless struct)
-		/wd4244 # conversion from double to float
-		/wd4305 # truncation from double to float
-		/wd5105 # see https://developercommunity.visualstudio.com/t/1249671
-	)
-endif()
-
-#------------------------------------------------------------------------------
-# PLATFORM-SPECIFIC PACKAGING
-#------------------------------------------------------------------------------
-
 set_target_properties(${GAME_TARGET} PROPERTIES
 	#--------------------------------------------------------------------------
 	# MSVC/WIN32
@@ -162,11 +95,11 @@
 	XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
 
 	# Set up Info.plist values
-	MACOSX_BUNDLE_ICON_FILE				"${GAME_TARGET}.icns"	# CFBundleIconFile
+	MACOSX_BUNDLE_ICON_FILE				"app.icns"	# CFBundleIconFile
 	MACOSX_BUNDLE_EXECUTABLE_NAME		${GAME_TARGET}			# CFBundleExecutable - executable name inside the bundle
 	MACOSX_BUNDLE_SHORT_VERSION_STRING	${PROJECT_VERSION}		# CFBundleShortVersionString
-	MACOSX_BUNDLE_COPYRIGHT				${GAME_MAC_COPYRIGHT}	# NSHumanReadableCopyright (supersedes CFBundleGetInfoString (MACOSX_BUNDLE_INFO_STRING))
-	MACOSX_BUNDLE_BUNDLE_NAME			${GAME_TARGET}			# CFBundleName - user-visible (where??) short name for the bundle, up to 15 characters
+#	MACOSX_BUNDLE_COPYRIGHT				${GAME_MAC_COPYRIGHT}	# NSHumanReadableCopyright (supersedes CFBundleGetInfoString (MACOSX_BUNDLE_INFO_STRING))
+	MACOSX_BUNDLE_BUNDLE_NAME			"Candy Crisis"			# CFBundleName - user-visible short name for the bundle
 	MACOSX_BUNDLE_GUI_IDENTIFIER		${GAME_MAC_BUNDLE_ID}	# CFBundleIdentifier - unique bundle ID in reverse-DNS format
 
 	# Bundle ID required for code signing - must match CFBundleIdentifier otherwise xcode will complain
@@ -175,60 +108,44 @@
 	# Don't bother with universal builds when we're working on the debug version
 	XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH[variant=Debug] "YES"
 
-	XCODE_EMBED_FRAMEWORKS							"${SDL2_LIBRARIES}"
-	XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY		"YES"		# frameworks must be signed by the same developer as the binary
-	XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY	"YES"		# not strictly necessary, but that's cleaner
 	XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME			"YES"		# required for notarization to pass
 )
 
-if(APPLE)
-	# If we have a code signing identity (CODE_SIGN_IDENTITY environment variable),
-	# set up the release build for proper code signing
-	if(NOT "$ENV{CODE_SIGN_IDENTITY}" STREQUAL "")
-		set_target_properties(${GAME_TARGET} PROPERTIES
-			XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY[variant=Release] "$ENV{CODE_SIGN_IDENTITY}"
-			XCODE_ATTRIBUTE_DEVELOPMENT_TEAM[variant=Release] "$ENV{CODE_SIGN_IDENTITY}"
+#------------------------------------------------------------------------------
+# LINK LIBRARIES
+#------------------------------------------------------------------------------
 
-			# The following is to pass notarization requirements
-			XCODE_ATTRIBUTE_CODE_SIGN_INJECT_BASE_ENTITLEMENTS[variant=Release] "NO"
-			XCODE_ATTRIBUTE_OTHER_CODE_SIGN_FLAGS[variant=Release] "--options=runtime --timestamp"
-		)
-		message("Release build will be code signed!")
-	endif()
+# SDL2::SDL2main may or may not be available. It is e.g. required by Windows GUI applications  
+if(TARGET SDL2::SDL2main)
+	# It has an implicit dependency on SDL2 functions, so it MUST be added before SDL2::SDL2 (or SDL2::SDL2-static)
+	target_link_libraries(${GAME_TARGET} PRIVATE SDL2::SDL2main)
+endif()
 
-	# Copy stuff to app bundle contents
-	set_source_files_properties(${GAME_MAC_ICNS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
-	#set_source_files_properties(${SDL2_LIBRARIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Frameworks")
+if(SYSTEM_SDL)
+	target_link_libraries(${GAME_TARGET} PRIVATE SDL2::SDL2)
+else()
+	target_link_libraries(${GAME_TARGET} PRIVATE SDL2::SDL2-static)
+endif()
 
-	set(BUNDLE_CONTENTS_DIR "$<TARGET_FILE_DIR:${PROJECT_NAME}>/..")
-	set(APP_PARENT_DIR "${BUNDLE_CONTENTS_DIR}/../..")
+#------------------------------------------------------------------------------
+# COPY ASSETS
+#------------------------------------------------------------------------------
 
-	add_custom_command(TARGET ${GAME_TARGET} POST_BUILD
-		# Copy assets to app bundle
-		COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/CandyCrisisResources ${BUNDLE_CONTENTS_DIR}/Resources
-
-		# High-DPI support in Info.plist
-#		plutil -replace NSHighResolutionCapable -bool true ${BUNDLE_CONTENTS_DIR}/Info.plist
-	)
+if(APPLE)
+	set(GAME_DATA_TARGET_LOCATION "$<TARGET_FILE_DIR:${PROJECT_NAME}>/../Resources")
 else()
-	set(APP_PARENT_DIR "$<TARGET_FILE_DIR:${GAME_TARGET}>")
-
-	# Copy assets besides executable
-	add_custom_command(TARGET ${GAME_TARGET} POST_BUILD
-		COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/CandyCrisisResources ${APP_PARENT_DIR}/CandyCrisisResources)
+	set(GAME_DATA_TARGET_LOCATION "$<TARGET_FILE_DIR:${PROJECT_NAME}>/CandyCrisisResources")
 endif()
 
-# Windows-specific libraries
-if(WIN32)
-	# Copy SDL2 DLLs to output folder on Windows for convenience
-	foreach(DLL ${SDL2_DLLS})
-		add_custom_command(TARGET ${GAME_TARGET} POST_BUILD
-			COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DLL} ${APP_PARENT_DIR})
-	endforeach()
+add_custom_command(TARGET ${GAME_TARGET} POST_BUILD
+	COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/CandyCrisisResources" "${GAME_DATA_TARGET_LOCATION}")
 
+#------------------------------------------------------------------------------
+# INSTALL
+#------------------------------------------------------------------------------
+
+# Install Windows-specific libraries
+if(WIN32)
 	# When installing (cmake --install), copy Visual Studio redistributable DLLs to install location
 	include(InstallRequiredSystemLibraries)
 endif()
-
-# Copy documentation to output folder
-configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packaging/ReadMe.txt.in ${CMAKE_CURRENT_BINARY_DIR}/ReadMe.txt)
--- a/build.py
+++ /dev/null
@@ -1,454 +1,0 @@
-#!/usr/bin/env python3
-
-import argparse
-import contextlib
-import hashlib
-import glob
-import multiprocessing
-import os
-import os.path
-import platform
-import shutil
-import stat
-import subprocess
-import sys
-import tempfile
-import urllib.request
-import zipfile
-from pathlib import Path
-
-#----------------------------------------------------------------
-
-libs_dir = os.path.abspath("extern")
-cache_dir = os.path.abspath("cache")
-dist_dir = os.path.abspath("dist")
-
-game_name           = "CandyCrisis"  # no spaces
-game_name_human     = "Candy Crisis"  # spaces and other special characters allowed
-game_ver            = "3.0.0"
-
-sdl_ver             = "2.0.20"
-appimagetool_ver    = "13"
-
-lib_hashes = {  # sha-256
-    "SDL2-2.0.20.tar.gz":           "c56aba1d7b5b0e7e999e4a7698c70b63a3394ff9704b5f6e1c57e0c16f04dd06",
-    "SDL2-2.0.20.dmg":              "e46a3694f5008c4c5ffd33e1dfdffbee64179ad15088781f2f70806dd0102d4d",
-    "SDL2-devel-2.0.20-VC.zip":     "5b1512ca6c9d2427bd2147da01e5e954241f8231df12f54a7074dccde416df18",
-    "appimagetool-x86_64.AppImage": "df3baf5ca5facbecfc2f3fa6713c29ab9cefa8fd8c1eac5d283b79cab33e4acb", # appimagetool v13
-}
-
-NPROC = multiprocessing.cpu_count()
-SYSTEM = platform.system()
-
-if SYSTEM == "Windows":
-    os.system("")  # hack to get ANSI color escapes to work
-
-#----------------------------------------------------------------
-
-parser = argparse.ArgumentParser(description=F"Configure, build, and package {game_name_human}")
-
-if SYSTEM == "Darwin":
-    default_generator = "Xcode"
-    default_architecture = None
-    help_configure = "generate Xcode project"
-    help_build = "build app from Xcode project"
-    help_package = "package up the game into a DMG"
-elif SYSTEM == "Windows":
-    default_generator = "Visual Studio 17 2022"
-    default_architecture = "x64"
-    help_configure = F"generate {default_generator} solution"
-    help_build = F"build exe from {default_generator} solution"
-    help_package = "package up the game into a ZIP"
-else:
-    default_generator = None
-    default_architecture = None
-    help_configure = "generate project"
-    help_build = "build binary"
-    help_package = "package up the game into an AppImage"
-
-parser.add_argument("--dependencies", default=False, action="store_true", help="fetch and set up dependencies (SDL)")
-parser.add_argument("--configure", default=False, action="store_true", help=help_configure)
-parser.add_argument("--build", default=False, action="store_true", help=help_build)
-parser.add_argument("--package", default=False, action="store_true", help=help_package)
-
-parser.add_argument("-G", metavar="<generator>", default=default_generator,
-        help=F"custom project generator for the CMake configure step (default: {default_generator})")
-
-parser.add_argument("-A", metavar="<arch>", default=default_architecture,
-        help=F"custom platform name for the CMake configure step (default: {default_architecture})")
-
-parser.add_argument("--print-artifact-name", default=False, action="store_true",
-        help="print artifact name and exit")
-
-if SYSTEM == "Linux":
-    parser.add_argument("--system-sdl", default=False, action="store_true",
-        help="use system SDL instead of building SDL from scratch")
-
-args = parser.parse_args()
-
-#----------------------------------------------------------------
-
-class Project:
-    def __init__(self, dir_name, gen_args=[], gen_env={}, build_configs=[], build_args=[]):
-        self.dir_name = dir_name
-        self.gen_args = gen_args
-        self.gen_env = gen_env
-        self.build_configs = build_configs
-        self.build_args = build_args
-
-#----------------------------------------------------------------
-
[email protected]
-def chdir(path):
-    origin = os.getcwd()
-    try:
-        os.chdir(path)
-        yield
-    finally:
-        os.chdir(origin)
-
-def die(message):
-    print(F"\x1b[1;31m{message}\x1b[0m", file=sys.stderr)
-    sys.exit(1)
-
-def log(message):
-    print(message, file=sys.stderr)
-
-def fatlog(message):
-    starbar = len(message) * '*'
-    print(F"\n{starbar}\n{message}\n{starbar}", file=sys.stderr)
-
-def hash_file(path):
-    hasher = hashlib.sha256()
-    with open(path, 'rb') as f:
-        while True:
-            chunk = f.read(64*1024)
-            if not chunk:
-                break
-            hasher.update(chunk)
-    return hasher.hexdigest()
-
-def get_package(url):
-    name = url[url.rfind('/')+1:]
-
-    if name in lib_hashes:
-        reference_hash = lib_hashes[name]
-    else:
-        die(F"Build script lacks reference checksum for {name}")
-
-    path = os.path.normpath(F"{cache_dir}/{name}")
-    if os.path.exists(path):
-        log(F"Not redownloading: {path}")
-    else:
-        log(F"Downloading: {url}")
-        os.makedirs(cache_dir, exist_ok=True)
-        urllib.request.urlretrieve(url, path)
-
-    actual_hash = hash_file(path)
-    if reference_hash != actual_hash:
-        die(F"Bad checksum for {name}: expected {reference_hash}, got {actual_hash}")
-
-    return path
-
-def call(cmd, **kwargs):
-    cmdstr = ""
-    for token in cmd:
-        cmdstr += " "
-        if " " in token:
-            cmdstr += F"\"{token}\""
-        else:
-            cmdstr += token
-
-    log(F">{cmdstr}")
-    try:
-        return subprocess.run(cmd, check=True, **kwargs)
-    except subprocess.CalledProcessError as e:
-        die(F"Aborting setup because: {e}")
-
-def rmtree_if_exists(path):
-    if os.path.exists(path):
-        shutil.rmtree(path)
-
-def zipdir(zipname, topleveldir, arc_topleveldir):
-    with zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED, compresslevel=9) as zipf:
-        for root, dirs, files in os.walk(topleveldir):
-            for file in files:
-                filepath = os.path.join(root, file)
-                arcpath = os.path.join(arc_topleveldir, filepath[len(topleveldir)+1:])
-                log(F"Zipping: {filepath} --> {arcpath}")
-                zipf.write(filepath, arcpath)
-
-#----------------------------------------------------------------
-
-def prepare_dependencies_windows():
-    rmtree_if_exists(F"{libs_dir}/SDL2-{sdl_ver}")
-
-    sdl_zip_path = get_package(F"http://libsdl.org/release/SDL2-devel-{sdl_ver}-VC.zip")
-    shutil.unpack_archive(sdl_zip_path, libs_dir)
-
-def prepare_dependencies_macos():
-    sdl2_framework = "SDL2.framework"
-    sdl2_framework_target_path = F"{libs_dir}/{sdl2_framework}"
-
-    rmtree_if_exists(sdl2_framework_target_path)
-
-    sdl_dmg_path = get_package(F"http://libsdl.org/release/SDL2-{sdl_ver}.dmg")
-
-    # Mount the DMG and copy SDL2.framework to extern/
-    with tempfile.TemporaryDirectory() as mount_point:
-        call(["hdiutil", "attach", sdl_dmg_path, "-mountpoint", mount_point, "-quiet"])
-        shutil.copytree(F"{mount_point}/{sdl2_framework}", sdl2_framework_target_path, symlinks=True)
-        call(["hdiutil", "detach", mount_point, "-quiet"])
-
-    if "CODE_SIGN_IDENTITY" in os.environ:
-        call(["codesign", "--force", "--timestamp", "--sign", os.environ["CODE_SIGN_IDENTITY"], sdl2_framework_target_path])
-    else:
-        print("SDL will not be codesigned. Set the CODE_SIGN_IDENTITY environment variable if you want to sign it.")
-
-def prepare_dependencies_linux():
-    if not args.system_sdl:
-        sdl_source_dir = F"{libs_dir}/SDL2-{sdl_ver}"
-        sdl_build_dir = F"{sdl_source_dir}/build"
-        rmtree_if_exists(sdl_source_dir)
-
-        sdl_zip_path = get_package(F"http://libsdl.org/release/SDL2-{sdl_ver}.tar.gz")
-        shutil.unpack_archive(sdl_zip_path, libs_dir)
-
-        with chdir(sdl_source_dir):
-            call([F"{sdl_source_dir}/configure", F"--prefix={sdl_build_dir}", "--quiet"])
-            call(["make", "-j", str(NPROC)], stdout=subprocess.DEVNULL)
-            call(["make", "install", "--silent"])  # install to configured prefix (sdl_build_dir)
-
-#----------------------------------------------------------------
-
-def get_artifact_name():
-    if SYSTEM == "Windows":
-        return F"{game_name}-{game_ver}-windows-x64.zip"
-    elif SYSTEM == "Darwin":
-        return F"{game_name}-{game_ver}-mac.dmg"
-    elif SYSTEM == "Linux":
-        return F"{game_name}-{game_ver}-linux-x86_64.AppImage"
-    else:
-        die("Unknown system for print_artifact_name")
-
-def copy_documentation(proj, appdir, full=True):
-    #shutil.copy(F"{proj.dir_name}/ReadMe.txt", F"{appdir}")
-    #shutil.copy(F"LICENSE.md", F"{appdir}/License.txt")
-
-    if full:
-        pass
-        #shutil.copytree("docs", F"{appdir}/Documentation")
-        # os.remove(F"{appdir}/Documentation/logo.png")
-        #os.remove(F"{appdir}/Documentation/screenshot.png")
-        #os.remove(F"{appdir}/Documentation/screenshot2.png")
-        #for docfile in ["CHANGELOG.md"]:
-        #    shutil.copy(docfile, F"{appdir}/Documentation")
-
-def package_windows(proj):
-    windows_dlls = ["SDL2.dll", "msvcp140.dll", "vcruntime140.dll", "vcruntime140_1.dll"]  # C++
-
-    # Prep DLLs with cmake (copied to {cache_dir}/install/bin)
-    call(["cmake", "--install", proj.dir_name, "--prefix", F"{cache_dir}/install"])
-
-    appdir = F"{cache_dir}/{game_name}-{game_ver}"
-    rmtree_if_exists(appdir)
-    os.makedirs(F"{appdir}", exist_ok=True)
-
-    # Copy executable, libs and assets
-    for dll in windows_dlls:
-        shutil.copy(F"{cache_dir}/install/bin/{dll}", appdir)
-    shutil.copy(F"{proj.dir_name}/Release/{game_name}.exe", appdir)
-    shutil.copytree("CandyCrisisResources", F"{appdir}/CandyCrisisResources")
-
-    copy_documentation(proj, appdir)
-
-    zipdir(F"{dist_dir}/{get_artifact_name()}", appdir, F"{game_name}-{game_ver}")
-
-def package_macos(proj):
-    appdir = F"{proj.dir_name}/Release"
-
-    # Human-friendly name for .app
-    os.rename(F"{appdir}/{game_name}.app", F"{appdir}/{game_name_human}.app")
-
-    copy_documentation(proj, appdir)
-
-    #shutil.copy("packaging/dmg_DS_Store", F"{appdir}/.DS_Store")
-
-    call(["hdiutil", "create",
-        "-fs", "HFS+",
-        "-srcfolder", appdir,
-        "-volname", F"{game_name_human} {game_ver}",
-        F"{dist_dir}/{get_artifact_name()}"])
-
-def package_linux(proj):
-    appimagetool_path = get_package(F"https://github.com/AppImage/AppImageKit/releases/download/{appimagetool_ver}/appimagetool-x86_64.AppImage")
-    os.chmod(appimagetool_path, 0o755)
-
-    appdir = F"{cache_dir}/{game_name}-{game_ver}.AppDir"
-    rmtree_if_exists(appdir)
-
-    os.makedirs(F"{appdir}", exist_ok=True)
-    os.makedirs(F"{appdir}/usr/bin", exist_ok=True)
-    os.makedirs(F"{appdir}/usr/lib", exist_ok=True)
-
-    # Copy executable and assets
-    shutil.copy(F"{proj.dir_name}/{game_name}", F"{appdir}/usr/bin")  # executable
-    shutil.copytree("CandyCrisisResources", F"{appdir}/CandyCrisisResources")
-    copy_documentation(proj, appdir, full=False)
-
-    # Copy XDG stuff
-    shutil.copy(F"packaging/{game_name.lower()}.desktop", appdir)
-    shutil.copy(F"packaging/{game_name.lower()}-desktopicon.png", appdir)
-
-    # Copy AppImage kicker script
-    shutil.copy(F"packaging/AppRun", appdir)
-    os.chmod(F"{appdir}/AppRun", 0o755)
-
-    # Copy SDL (if not using system SDL)
-    if not args.system_sdl:
-        for file in glob.glob(F"{libs_dir}/SDL2-{sdl_ver}/build/lib/libSDL2*.so*"):
-            shutil.copy(file, F"{appdir}/usr/lib", follow_symlinks=False)
-
-    # Invoke appimagetool
-    call([appimagetool_path, "--no-appstream", appdir, F"{dist_dir}/{get_artifact_name()}"])
-
-#----------------------------------------------------------------
-
-if args.print_artifact_name:
-    print(get_artifact_name())
-    sys.exit(0)
-
-fatlog(F"{game_name} {game_ver} build script")
-
-if not (args.dependencies or args.configure or args.build or args.package):
-    log("No build steps specified, running all of them.")
-    args.dependencies = True
-    args.configure = True
-    args.build = True
-    args.package = True
-
-# Make sure we're running from the correct directory...
-if not os.path.exists("src/graymonitor.cpp"):  # some file that's likely to be from the game's source tree
-    die(F"STOP - Please run this script from the root of the {game_name} source repo")
-
-#----------------------------------------------------------------
-# Set up project metadata
-
-projects = []
-
-common_gen_args = []
-if args.G:
-    common_gen_args += ["-G", args.G]
-if args.A:
-    common_gen_args += ["-A", args.A]
-
-if SYSTEM == "Windows":
-
-    projects = [Project(
-        dir_name="build-msvc",
-        gen_args=common_gen_args,
-        build_configs=["Release", "Debug"],
-        build_args=["-m"]  # multiprocessor compilation
-    )]
-
-elif SYSTEM == "Darwin":
-    projects = [Project(
-        dir_name="build-xcode",
-        gen_args=common_gen_args,
-        build_configs=["Release"],
-        build_args=["-j", str(NPROC)]
-    )]
-
-elif SYSTEM == "Linux":
-    gen_env = {}
-    if not args.system_sdl:
-        gen_env["SDL2DIR"] = F"{libs_dir}/SDL2-{sdl_ver}/build"
-
-    projects.append(Project(
-        dir_name="build-relwithdebinfo",
-        gen_args=common_gen_args + ["-DCMAKE_BUILD_TYPE=RelWithDebInfo"],
-        gen_env=gen_env,
-        build_args=["-j", str(NPROC)]
-    ))
-
-    projects.append(Project(
-        dir_name="build-debug",
-        gen_args=common_gen_args + ["-DCMAKE_BUILD_TYPE=Debug"],
-        gen_env=gen_env,
-        build_args=["-j", str(NPROC)]
-    ))
-else:
-    die(F"Unsupported system for configure step: {SYSTEM}")
-
-
-#----------------------------------------------------------------
-# Prepare dependencies
-
-if args.dependencies:
-    fatlog("Setting up dependencies")
-
-    # Check that our submodules are here
-    #if not os.path.exists("extern/Pomme/CMakeLists.txt"):
-    #    die("Submodules appear to be missing.\n"
-    #        + "Did you clone the submodules recursively? Try this:    git submodule update --init --recursive")
-
-    if SYSTEM == "Windows":
-        prepare_dependencies_windows()
-    elif SYSTEM == "Darwin":
-        prepare_dependencies_macos()
-    elif SYSTEM == "Linux":
-        prepare_dependencies_linux()
-    else:
-        die(F"Unsupported system for dependencies step: {SYSTEM}")
-
-#----------------------------------------------------------------
-# Configure projects
-
-if args.configure:
-    for proj in projects:
-        fatlog(F"Configuring {proj.dir_name}")
-
-        rmtree_if_exists(proj.dir_name)
-
-        env = None
-        if proj.gen_env:
-            env = os.environ.copy()
-            env.update(proj.gen_env)
-
-        call(["cmake", "-S", ".", "-B", proj.dir_name] + proj.gen_args, env=env)
-
-#----------------------------------------------------------------
-# Build the game
-
-proj = projects[0]
-
-if args.build:
-    fatlog(F"Building the game: {proj.dir_name}")
-
-    build_command = ["cmake", "--build", proj.dir_name]
-
-    if proj.build_configs:
-        build_command += ["--config", proj.build_configs[0]]
-
-    if proj.build_args:
-        build_command += ["--"] + proj.build_args
-
-    call(build_command)
-
-#----------------------------------------------------------------
-# Package the game
-
-if args.package:
-    fatlog(F"Packaging the game")
-
-    rmtree_if_exists(dist_dir)
-    os.makedirs(dist_dir, exist_ok=True)
-
-    if SYSTEM == "Darwin":
-        package_macos(proj)
-    elif SYSTEM == "Windows":
-        package_windows(proj)
-    elif SYSTEM == "Linux":
-        package_linux(proj)
-    else:
-        die(F"Unsupported system for package step: {SYSTEM}")
--- a/cmake/FindSDL2.cmake
+++ /dev/null
@@ -1,74 +1,0 @@
-#------------------------------------------------------------------------------
-# Usage: find_package(SDL2 [REQUIRED] [COMPONENTS main])
-#
-# Sets variables:
-#     SDL2_INCLUDE_DIRS
-#     SDL2_LIBRARIES
-#     SDL2_DLLS (Windows only)
-#------------------------------------------------------------------------------
-
-include(FindPackageHandleStandardArgs)
-
-set(SDL2_VERSION 2.0.20)
-
-# Check if "main" was specified as a component
-set(_SDL2_use_main FALSE)
-foreach(_SDL2_component ${SDL2_FIND_COMPONENTS})
-    if(_SDL2_component STREQUAL "main")
-        set(_SDL2_use_main TRUE)
-    else()
-        message(WARNING "Unrecognized component \"${_SDL2_component}\"")
-    endif()
-endforeach()
-
-if(WIN32)
-    find_path(SDL2_ROOT "include/SDL.h"
-        PATHS "${CMAKE_SOURCE_DIR}/extern/SDL2-${SDL2_VERSION}"
-        NO_DEFAULT_PATH
-    )
-    
-    if(SDL2_ROOT)
-        set(SDL2_INCLUDE_DIRS "${SDL2_ROOT}/include")
-        set(_SDL2_ARCH "x64")
-        set(SDL2_LIBRARIES "${SDL2_ROOT}/lib/${_SDL2_ARCH}/SDL2.lib")
-        set(SDL2_DLLS "${SDL2_ROOT}/lib/${_SDL2_ARCH}/SDL2.dll")
-        if(_SDL2_use_main)
-            list(APPEND SDL2_LIBRARIES "${SDL2_ROOT}/lib/${_SDL2_ARCH}/SDL2main.lib")
-        endif()
-
-        # When installing, copy DLLs to install location
-        install(FILES ${SDL2_DLLS} DESTINATION bin)
-    endif()
-
-    mark_as_advanced(SDL2_ROOT)
-    find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_INCLUDE_DIRS SDL2_LIBRARIES SDL2_DLLS)
-
-elseif(APPLE)
-    find_path(SDL2_INCLUDE_DIRS "SDL.h"
-        PATHS "${CMAKE_SOURCE_DIR}/extern/SDL2.framework/Versions/Current"
-        PATH_SUFFIXES "Headers"
-        REQUIRED
-        NO_DEFAULT_PATH
-    )
-
-    set(SDL2_LIBRARIES "${CMAKE_SOURCE_DIR}/extern/SDL2.framework")
-
-    find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_INCLUDE_DIRS SDL2_LIBRARIES)
-
-else()
-    find_path(SDL2_INCLUDE_DIRS "SDL.h"
-        HINTS $ENV{SDL2DIR}
-        PATH_SUFFIXES "include/SDL2" "include"
-        REQUIRED
-    )
-
-    find_library(SDL2_LIBRARIES
-        NAMES "SDL2"
-        HINTS $ENV{SDL2DIR}
-        PATH_SUFFIXES lib64 lib
-        REQUIRED
-    )
-
-    find_package_handle_standard_args(SDL2 DEFAULT_MSG SDL2_INCLUDE_DIRS SDL2_LIBRARIES)
-
-endif()
--- a/cmake/version.h.in
+++ /dev/null
@@ -1,7 +1,0 @@
-#pragma once
-
-#define PROJECT_VERSION "@PROJECT_VERSION@"
-#define PROJECT_VERSION_MAJOR "@PROJECT_VERSION_MAJOR@"
-#define PROJECT_VERSION_MINOR "@PROJECT_VERSION_MINOR@"
-#define PROJECT_VERSION_PATCH "@PROJECT_VERSION_PATCH@"
-
--- a/packaging/CandyCrisis.exe.rc
+++ /dev/null
@@ -1,1 +1,0 @@
-IDI_ICON1 ICON DISCARDABLE "CandyCrisis.ico"
binary files a/packaging/CandyCrisis.icns /dev/null differ
binary files a/packaging/CandyCrisis.ico /dev/null differ
--- /dev/null
+++ b/packaging/app.exe.rc
@@ -1,0 +1,39 @@
+#include <windows.h>
+#include "version.h"
+
+#pragma code_page(1252)
+
+#define PROJECT_VERSION_4_WORDS PROJECT_VERSION_MAJOR,PROJECT_VERSION_MINOR,PROJECT_VERSION_PATCH,0
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+//
+// IMPORTANT: The .ico should be UNCOMPRESSED, as a png-compressed .ico
+// may cause garbage AVs to flag the game as a false positive!
+IDI_ICON1 ICON DISCARDABLE "app.ico"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION     PROJECT_VERSION_4_WORDS
+PRODUCTVERSION  PROJECT_VERSION_4_WORDS
+FILEOS          VOS_NT_WINDOWS32
+FILETYPE        VFT_APP
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0" // US English cp1252 (hex)
+        BEGIN
+            VALUE "CompanyName",        "Candy Crisis"
+            VALUE "FileDescription",    "Candy Crisis"
+            VALUE "FileVersion",        PROJECT_VERSION
+            VALUE "InternalName",       "Candy Crisis"
+            VALUE "LegalCopyright",     "Candy Crisis"
+            VALUE "OriginalFilename",   "CandyCrisis.exe"
+            VALUE "ProductName",        "Candy Crisis"
+            VALUE "ProductVersion",     PROJECT_VERSION
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1252 // US English cp1252
+    END
+END
binary files /dev/null b/packaging/app.icns differ
binary files /dev/null b/packaging/app.ico differ
--- a/packaging/gon-config.json
+++ /dev/null
@@ -1,7 +1,0 @@
-{
-    "notarize": [{
-        "path": "./dist/CandyCrisis-3.0.0-mac.dmg",
-        "bundle_id": "io.jor.candycrisis",
-        "staple": true
-    }]
-}
--- /dev/null
+++ b/packaging/prepare_appimage_appdir.sh
@@ -1,0 +1,25 @@
+#! /usr/bin/env bash
+
+set -e
+
+EXE_PATH="$1"
+
+[[ ! -f "${EXE_PATH}" ]] && echo "must pass valid exe path" && exit 1
+
+APP_NAME="$(basename "${EXE_PATH}")"
+APP_NAME_LOWERCASE="$(echo "$APP_NAME" | awk '{print tolower($0)}')"
+APP_DIR="build/${APP_NAME}.AppDir"
+
+mkdir -p "${APP_DIR}/usr/bin"
+
+# Copy executable and assets
+cp "${EXE_PATH}" "${APP_DIR}/usr/bin"
+cp -r CandyCrisisResources "${APP_DIR}/CandyCrisisResources"
+
+# Copy XDG stuff
+cp "packaging/${APP_NAME_LOWERCASE}.desktop" "${APP_DIR}"
+cp "packaging/${APP_NAME_LOWERCASE}-desktopicon.png" "${APP_DIR}"
+
+# Copy AppImage kicker script
+cp "packaging/AppRun" "${APP_DIR}"
+chmod 755 "${APP_DIR}/AppRun"
--- a/src/version.h
+++ b/src/version.h
@@ -1,7 +1,7 @@
 #pragma once
 
 #define PROJECT_VERSION "3.0.0"
-#define PROJECT_VERSION_MAJOR "3"
-#define PROJECT_VERSION_MINOR "0"
-#define PROJECT_VERSION_PATCH "0"
+#define PROJECT_VERSION_MAJOR 3
+#define PROJECT_VERSION_MINOR 0
+#define PROJECT_VERSION_PATCH 0
 
--- /dev/null
+++ b/src/version.h.in
@@ -1,0 +1,7 @@
+#pragma once
+
+#define PROJECT_VERSION "@PROJECT_VERSION@"
+#define PROJECT_VERSION_MAJOR @PROJECT_VERSION_MAJOR@
+#define PROJECT_VERSION_MINOR @PROJECT_VERSION_MINOR@
+#define PROJECT_VERSION_PATCH @PROJECT_VERSION_PATCH@
+