Skip to content

Commit

Permalink
Add Windows support, start transition to CMake
Browse files Browse the repository at this point in the history
* Correctly list available playdate packages on Windows

* Add support for Windows using MinGW and CMake

* Update version and README.md
  • Loading branch information
samdze authored Jul 28, 2023
1 parent e4f0bdc commit dd5269e
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 20 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,10 @@ This package is an independent bindings library, not affiliated with Panic.
- Nim 1.6.10+ (check with `nim -v`)
- Nimble 0.13.1 (check with `nimble -v`)
- `PLAYDATE_SDK_PATH` environment variable
- Linux or macOS (Windows support is still WIP)
- [SDK Prerequisites](https://sdk.play.date/Inside%20Playdate%20with%20C.html#_prerequisites) based on OS
- [SDK Prerequisites](https://sdk.play.date/Inside%20Playdate%20with%20C.html#_prerequisites) based on OS, and:
- Linux: a C compiler, Make, `arm-none-eabi-newlib`.
- macOS: a C compiler, Make. Included in Xcode Command Line Tools.
- Windows: MinGW, CMake, Make. [Getting started](https://code.visualstudio.com/docs/cpp/config-mingw)

### Installation

Expand Down
2 changes: 1 addition & 1 deletion playdate.nimble
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Package

version = "0.8.1"
version = "0.8.5"
author = "Samuele Zolfanelli"
description = "Playdate Nim bindings with extra features."
license = "MIT"
Expand Down
12 changes: 9 additions & 3 deletions playdate_example/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
"request": "launch",
"name": "Debug PDX",
"program": "${env:PLAYDATE_SDK_PATH}/bin/Playdate Simulator",
"args": ["${workspaceFolder}/playdate_example.pdx"],
"args": [
"${workspaceFolder}/playdate_example.pdx"
],
"cwd": "${workspaceFolder}",
"osx": {
"MIMode": "lldb",
Expand All @@ -30,7 +32,9 @@
"name": "Build & Debug PDX",
"program": "${env:PLAYDATE_SDK_PATH}/bin/Playdate Simulator",
"preLaunchTask": "Build Universal PDX",
"args": ["${workspaceFolder}/playdate_example.pdx"],
"args": [
"${workspaceFolder}/playdate_example.pdx"
],
"cwd": "${workspaceFolder}",
"osx": {
"MIMode": "lldb",
Expand All @@ -51,7 +55,9 @@
"name": "Build Sim. & Debug PDX",
"program": "${env:PLAYDATE_SDK_PATH}/bin/Playdate Simulator",
"preLaunchTask": "Build Simulator PDX",
"args": ["${workspaceFolder}/playdate_example.pdx"],
"args": [
"${workspaceFolder}/playdate_example.pdx"
],
"cwd": "${workspaceFolder}",
"osx": {
"MIMode": "lldb",
Expand Down
13 changes: 13 additions & 0 deletions playdate_example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# Template CMakeLists.txt, customize it if necessary
#

cmake_minimum_required(VERSION 3.14)
set(CMAKE_C_STANDARD 11)

# Setup the project and its name from the environment
set(PLAYDATE_PROJECT_NAME $ENV{PROJECT})
project(${PLAYDATE_PROJECT_NAME} C ASM)

# Include the playdate module CMake configuration
include($ENV{PLAYDATE_MODULE}/playdate.cmake)
13 changes: 13 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# Template CMakeLists.txt, customize it if necessary
#

cmake_minimum_required(VERSION 3.14)
set(CMAKE_C_STANDARD 11)

# Setup the project and its name from the environment
set(PLAYDATE_PROJECT_NAME $ENV{PROJECT})
project(${PLAYDATE_PROJECT_NAME} C ASM)

# Include the playdate module CMake configuration
include($ENV{PLAYDATE_MODULE}/playdate.cmake)
119 changes: 119 additions & 0 deletions src/playdate.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
#
# CMake include file for Playdate games
#
cmake_minimum_required(VERSION 3.19)

set(ENVSDK $ENV{PLAYDATE_SDK_PATH})
set(NIM_CACHE_DIR $ENV{NIM_CACHE_DIR})
set(UINCDIR $ENV{UINCDIR})

if (NOT ${ENVSDK} STREQUAL "")
# Convert path from Windows
file(TO_CMAKE_PATH ${ENVSDK} SDK)
else()
execute_process(
COMMAND bash -c "egrep '^\\s*SDKRoot' $HOME/.Playdate/config"
COMMAND head -n 1
COMMAND cut -c9-
OUTPUT_VARIABLE SDK
OUTPUT_STRIP_TRAILING_WHITESPACE
)
endif()

if (NOT EXISTS ${SDK})
message(FATAL_ERROR "SDK Path not found; set ENV value PLAYDATE_SDK_PATH")
return()
endif()

set(CMAKE_CONFIGURATION_TYPES "Debug;Release")
set(CMAKE_XCODE_GENERATE_SCHEME TRUE)

file(GLOB nim_source_files "${NIM_CACHE_DIR}/*.c")

# Game Name Customization
set(PLAYDATE_GAME_NAME ${PLAYDATE_PROJECT_NAME})
set(PLAYDATE_GAME_DEVICE ${PLAYDATE_PROJECT_NAME})

# Include Nim required headers
include_directories(${UINCDIR})

if (TOOLCHAIN STREQUAL "armgcc")
add_executable(${PLAYDATE_GAME_DEVICE} ${nim_source_files})
target_link_libraries(${PLAYDATE_GAME_DEVICE} rdimon c m gcc nosys)
else()
add_library(${PLAYDATE_GAME_NAME} SHARED ${nim_source_files})
endif()

include(${SDK}/C_API/buildsupport/playdate.cmake)

set(BUILD_SUB_DIR "")

if (TOOLCHAIN STREQUAL "armgcc")
set_property(TARGET ${PLAYDATE_GAME_DEVICE} PROPERTY OUTPUT_NAME "${PLAYDATE_GAME_DEVICE}.elf")

add_custom_command(
TARGET ${PLAYDATE_GAME_DEVICE} POST_BUILD
COMMAND ${CMAKE_STRIP} --strip-unneeded -R .comment -g
${PLAYDATE_GAME_DEVICE}.elf
-o ${CMAKE_CURRENT_SOURCE_DIR}/Source/pdex.elf
)

add_custom_command(
TARGET ${PLAYDATE_GAME_DEVICE} POST_BUILD
COMMAND ${PDC} Source ${PLAYDATE_GAME_NAME}.pdx
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)

set_property(
TARGET ${PLAYDATE_GAME_DEVICE} PROPERTY ADDITIONAL_CLEAN_FILES
${CMAKE_CURRENT_SOURCE_DIR}/${PLAYDATE_GAME_NAME}.pdx
)

else ()

if (MSVC)
# MSVC not supported
message(FATAL_ERROR "MSVC is not supported! Use MinGW.")

elseif(MINGW)
target_compile_definitions(${PLAYDATE_GAME_NAME} PUBLIC _WINDLL=1)
add_custom_command(
TARGET ${PLAYDATE_GAME_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/lib${PLAYDATE_GAME_NAME}.dll
${CMAKE_CURRENT_SOURCE_DIR}/Source/pdex.dll)

elseif(APPLE)
if(${CMAKE_GENERATOR} MATCHES "Xcode" )
set(BUILD_SUB_DIR $<CONFIG>/)
set_property(TARGET ${PLAYDATE_GAME_NAME} PROPERTY XCODE_SCHEME_ARGUMENTS \"${CMAKE_CURRENT_SOURCE_DIR}/${PLAYDATE_GAME_NAME}.pdx\")
set_property(TARGET ${PLAYDATE_GAME_NAME} PROPERTY XCODE_SCHEME_EXECUTABLE ${SDK}/bin/Playdate\ Simulator.app)
endif()

add_custom_command(
TARGET ${PLAYDATE_GAME_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/${BUILD_SUB_DIR}lib${PLAYDATE_GAME_NAME}.dylib
${CMAKE_CURRENT_SOURCE_DIR}/Source/pdex.dylib)

elseif(UNIX)
add_custom_command(
TARGET ${PLAYDATE_GAME_NAME} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_BINARY_DIR}/lib${PLAYDATE_GAME_NAME}.so
${CMAKE_CURRENT_SOURCE_DIR}/Source/pdex.so)
else()
message(FATAL_ERROR "Platform not supported!")
endif()

set_property(
TARGET ${PLAYDATE_GAME_NAME} PROPERTY ADDITIONAL_CLEAN_FILES
${CMAKE_CURRENT_SOURCE_DIR}/${PLAYDATE_GAME_NAME}.pdx
)

add_custom_command(
TARGET ${PLAYDATE_GAME_NAME} POST_BUILD
COMMAND ${PDC} ${CMAKE_CURRENT_SOURCE_DIR}/Source
${CMAKE_CURRENT_SOURCE_DIR}/${PLAYDATE_GAME_NAME}.pdx)

endif ()
4 changes: 4 additions & 0 deletions src/playdate/api.nim
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{.push raises: [].}

import macros
import std/importutils

import bindings/utils {.all.} as memory
import bindings/api
export api

Expand All @@ -13,9 +15,11 @@ macro initSDK*() =
proc NimMain() {.importc.}

proc eventHandler(playdateAPI: ptr PlaydateAPI, event: PDSystemEvent, arg: uint32): cint {.cdecl, exportc.} =
privateAccess(PlaydateSys)
if event == kEventInit:
NimMain()
api.playdate = playdateAPI
memory.realloc = playdateAPI.system.realloc
handler(event, arg)
return 0

Expand Down
2 changes: 1 addition & 1 deletion src/playdate/bindings/utils.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import macros

proc realloc*(p: pointer, size: csize_t): pointer {.importc: "realloc", cdecl.}
var realloc*: proc(p: pointer, size: csize_t): pointer {.cdecl.}

func toNimSymbol(typeSymbol: string): string =
case typeSymbol:
Expand Down
47 changes: 34 additions & 13 deletions src/playdate/build/nimble.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ type BuildFail = object of Defect

proc playdatePath(): string =
## Returns the path of the playdate nim module
let (paths, exitCode) = gorgeEx("nimble path playdate")
var (paths, exitCode) = gorgeEx("nimble path playdate")
paths.stripLineEnd()
if exitCode != 0:
raise BuildFail.newException("Could not find the playdate nimble module!")
let pathsSeq = paths.split("\n")
let pathsSeq = paths.splitLines(false)
# If multiple package paths are found, use the last one
let path = pathsSeq[pathsSeq.len - 1]
if path.strip == "" or not path.strip.dirExists:
Expand Down Expand Up @@ -50,22 +51,42 @@ proc sdkPath*(): string =

proc make(target: string) =
## Executes a make target

let makefile = playdatePath() & "/playdate.mk"
if not makefile.fileExists:
raise BuildFail.newException("Could not find playdate Makefile: " & makefile)

putEnv(SDK_ENV_VAR, sdkPath())
putEnv("NIM_CACHE_DIR", nimcacheDir())
putEnv("NIM_CACHE_DIR", nimcacheDir().replace(DirSep, '/'))
putEnv("PLAYDATE_MODULE", playdatePath())
putEnv("PRODUCT", pdxName())
putEnv("PROJECT", projectName())
putEnv("UINCDIR", getCurrentCompilerExe().parentDir.parentDir / "lib")

if defined(windows):
# Handle Windows differently for now, needs CMake
if target == "clean":
rmDir("build", false)
return
if not fileExists("CMakeLists.txt"):
cpFile(os.joinPath(playdatePath(), "CMakeLists.txt"), "CMakeLists.txt")
mkDir("build")
cd("build")
if target == "simulator" or target == "pdc":
exec("cmake --fresh .. -DCMAKE_BUILD_TYPE=Debug" & " -G \"MinGW Makefiles\"")
exec("make")
elif target == "device":
exec("cmake --fresh .. -DCMAKE_BUILD_TYPE=Release" & " -G \"Unix Makefiles\" --toolchain=" & os.joinPath(sdkPath(), "C_API", "buildsupport", "arm.cmake"))
exec("make")
cd("..")
else:
let makefile = playdatePath() & "/playdate.mk"
if not makefile.fileExists:
raise BuildFail.newException("Could not find playdate Makefile: " & makefile)
let arch = if defined(macosx): "arch -arm64 " else: ""
exec(arch & "make " & target & " -f " & makefile)

proc cleanCache() =
rmDir(nimcacheDir())

let arch = if defined(macosx): "arch -arm64 " else: ""
exec(arch & "make " & target & " -f " & makefile)

task clean, "Clean the project folders":
if dirExists(nimcacheDir()):
exec "rm -fR " & nimcacheDir()
cleanCache()
make "clean"

task cdevice, "Generate C files for the device":
Expand All @@ -92,7 +113,7 @@ task all, "Build for both the simulator and the device":
nimble "clean"
nimble "csim"
make "simulator"
exec "rm -fR " & nimcacheDir()
cleanCache()
nimble "cdevice"
make "device"
exec(sdkPath() & "/bin/pdc Source " & pdxName())
Expand Down

0 comments on commit dd5269e

Please sign in to comment.