ref: ceb09f7ffd02027f1f1be6242b9190f15398bcc2
parent: dbf642749d4890bced0a237d5c512ff0f8083b51
author: Iliyas Jorio <[email protected]>
date: Wed Feb 2 17:21:35 EST 2022
Cross-platform CI
--- /dev/null
+++ b/.github/workflows/CompileCheck.yml
@@ -1,0 +1,32 @@
+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 }}
--- /dev/null
+++ b/.github/workflows/ReleaseBuilds.yml
@@ -1,0 +1,80 @@
+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 }}
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,5 @@
-cmake-build-*
-
+build-*/
+cache/
+cmake-build-*/
+dist/
+extern/
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,13 +1,235 @@
-cmake_minimum_required(VERSION 3.16)
-project(CandyCrisis)
+cmake_minimum_required(VERSION 3.13)
-set(CMAKE_CXX_STANDARD 17)
+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")
-find_package(SDL2 REQUIRED)
-include_directories(${SDL2_INCLUDE_DIRS})
+set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
+set(CMAKE_C_STANDARD 17)
+set(CMAKE_CXX_STANDARD 17)
-file(GLOB_RECURSE GAME_SOURCES CONFIGURE_DEPENDS src/*.cpp src/*.c src/*.h)
+set(CMAKE_OSX_DEPLOYMENT_TARGET "10.11" CACHE STRING "Minimum OS X deployment version")
+set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE STRING "Target macOS architectures")
-add_executable(CandyCrisis ${GAME_SOURCES})
+project(${GAME_TARGET}
+ VERSION ${GAME_VERSION}
+ LANGUAGES C CXX
+)
-target_link_libraries(CandyCrisis ${SDL2_LIBRARIES} ${SDL2_IMAGE_LIBRARIES} SDL2)
+#------------------------------------------------------------------------------
+# GLOBAL OPTIONS (BEFORE ADDING SUBDIRECTORIES)
+#------------------------------------------------------------------------------
+
+if(MSVC)
+ add_compile_definitions(UNICODE _UNICODE)
+
+ set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT ${GAME_TARGET})
+endif()
+
+#------------------------------------------------------------------------------
+# DEPENDENCIES
+#------------------------------------------------------------------------------
+
+find_package(SDL2 REQUIRED COMPONENTS main)
+
+#------------------------------------------------------------------------------
+# GAME SOURCES
+#------------------------------------------------------------------------------
+
+set(GAME_SRCDIR ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
+# 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
+#------------------------------------------------------------------------------
+
+source_group(TREE ${GAME_SRCDIR} PREFIX "" FILES ${GAME_ALL_SOURCES})
+
+#------------------------------------------------------------------------------
+# EXECUTABLE TARGET
+#------------------------------------------------------------------------------
+
+set(GAME_LIBRARIES ${SDL2_LIBRARIES})
+
+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"
+ )
+elseif(APPLE)
+ add_executable(${GAME_TARGET} MACOSX_BUNDLE
+ ${GAME_ALL_SOURCES}
+ ${GAME_MAC_ICNS}
+ ${SDL2_LIBRARIES}
+ )
+else()
+ # Math lib, explicitly required on some Linux systems
+ list(APPEND GAME_LIBRARIES m)
+
+ add_executable(${GAME_TARGET} ${GAME_ALL_SOURCES})
+endif()
+
+target_include_directories(${GAME_TARGET} PRIVATE
+ ${SDL2_INCLUDE_DIRS}
+ ${GAME_SRCDIR}
+)
+
+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-sign-compare # 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
+ #--------------------------------------------------------------------------
+
+ VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
+ VS_DPI_AWARE "PerMonitor"
+
+ #--------------------------------------------------------------------------
+ # APPLE
+ #--------------------------------------------------------------------------
+
+ # Set framework search path to (App bundle)/Contents/Frameworks so the game can use its embedded SDL2.framework
+ XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/../Frameworks"
+
+ # Explicitly turn off code signing, otherwise downloaded app will be quarantined forever
+ XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY ""
+
+ # Set up Info.plist values
+ MACOSX_BUNDLE_ICON_FILE "${GAME_TARGET}.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_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
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER ${GAME_MAC_BUNDLE_ID}
+
+ # 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}"
+
+ # 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()
+
+ # 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")
+
+ set(BUNDLE_CONTENTS_DIR "$<TARGET_FILE_DIR:${PROJECT_NAME}>/..")
+ set(APP_PARENT_DIR "${BUNDLE_CONTENTS_DIR}/../..")
+
+ 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
+ )
+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)
+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()
+
+ # 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)
--- /dev/null
+++ b/build.py
@@ -1,0 +1,454 @@
+#!/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}")
--- /dev/null
+++ b/cmake/FindSDL2.cmake
@@ -1,0 +1,74 @@
+#------------------------------------------------------------------------------
+# 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()
--- /dev/null
+++ b/cmake/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@"
+
--- /dev/null
+++ b/packaging/AppRun
@@ -1,0 +1,13 @@
+#!/bin/sh
+SELF=$(readlink -f "$0")
+HERE=${SELF%/*}
+export PATH="${HERE}/usr/bin/:${HERE}/usr/sbin/:${HERE}/usr/games/:${HERE}/bin/:${HERE}/sbin/${PATH:+:$PATH}"
+export LD_LIBRARY_PATH="${HERE}/usr/lib/:${HERE}/usr/lib/i386-linux-gnu/:${HERE}/usr/lib/x86_64-linux-gnu/:${HERE}/usr/lib32/:${HERE}/usr/lib64/:${HERE}/lib/:${HERE}/lib/i386-linux-gnu/:${HERE}/lib/x86_64-linux-gnu/:${HERE}/lib32/:${HERE}/lib64/${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
+export PYTHONPATH="${HERE}/usr/share/pyshared/${PYTHONPATH:+:$PYTHONPATH}"
+export XDG_DATA_DIRS="${HERE}/usr/share/${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}"
+export PERLLIB="${HERE}/usr/share/perl5/:${HERE}/usr/lib/perl5/${PERLLIB:+:$PERLLIB}"
+export GSETTINGS_SCHEMA_DIR="${HERE}/usr/share/glib-2.0/schemas/${GSETTINGS_SCHEMA_DIR:+:$GSETTINGS_SCHEMA_DIR}"
+export QT_PLUGIN_PATH="${HERE}/usr/lib/qt4/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt4/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt4/plugins/:${HERE}/usr/lib32/qt4/plugins/:${HERE}/usr/lib64/qt4/plugins/:${HERE}/usr/lib/qt5/plugins/:${HERE}/usr/lib/i386-linux-gnu/qt5/plugins/:${HERE}/usr/lib/x86_64-linux-gnu/qt5/plugins/:${HERE}/usr/lib32/qt5/plugins/:${HERE}/usr/lib64/qt5/plugins/${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH}"
+EXEC=$(grep -e '^Exec=.*' "${HERE}"/*.desktop | head -n 1 | cut -d "=" -f 2 | cut -d " " -f 1)
+cd $HERE
+exec "${EXEC}" "$@"
--- /dev/null
+++ b/packaging/CandyCrisis.exe.rc
@@ -1,0 +1,1 @@
+IDI_ICON1 ICON DISCARDABLE "CandyCrisis.ico"
--- /dev/null
+++ b/packaging/ReadMe.txt.in
@@ -1,0 +1,2 @@
+Candy Crisis source port @PROJECT_VERSION@
+https://github.com/jorio/candycrisis
binary files /dev/null b/packaging/candycrisis-desktopicon.png differ
--- /dev/null
+++ b/packaging/candycrisis.desktop
@@ -1,0 +1,9 @@
+[Desktop Entry]
+Type=Application
+Version=1.0
+Name=Candy Crisis
+Comment=Candy Crisis
+Icon=candycrisis-desktopicon
+Exec=CandyCrisis
+Terminal=false
+Categories=Game;
--- /dev/null
+++ b/packaging/gon-config.json
@@ -1,0 +1,7 @@
+{
+ "notarize": [{
+ "path": "./dist/CandyCrisis-3.0.0-mac.dmg",
+ "bundle_id": "io.jor.candycrisis",
+ "staple": true
+ }]
+}
--- a/src/stdafx.h
+++ b/src/stdafx.h
@@ -4,15 +4,13 @@
#pragma once
-#include <SDL2/SDL.h>
-#include <SDL2/SDL_endian.h>
+#include <SDL.h>
+#include <SDL_endian.h>
#if _WIN32
#define _CRT_SECURE_NO_WARNINGS 1
-#include "targetver.h"
-
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>
@@ -22,8 +20,5 @@
#include <malloc.h>
#include <memory.h>
#include <tchar.h>
-
-#include "SDL.h"
-#include "SDL_endian.h"
#endif
--- /dev/null
+++ b/src/version.h
@@ -1,0 +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"
+