Support for Swift Runtime

Yes a way to compile for arm64 / intel would be a fine target for now! Can we make an open source repo for this kind of work, or would that violate some license? It would be trivial to make a pure C SPM package and then we could get to work on making a swiftified wrapper package around it.

That is the plan, though I am not sure it is trivial. Trying to get it working now :smiley: I can set up a repo if it makes sense to. Will be on a plane soon with plenty of time.

I made a little headway getting something to compile. In case it's useful, here's what I have so far:

Put the following lines in a file called Playdate-Bridging-Header.h:

#define TARGET_EXTENSION 1
#include <pd_api.h>

And main.swift:

var savedAPI: PlaydateAPI?

func update(_: UnsafeMutableRawPointer?) -> Int32 {
    let playdate = savedAPI!

    playdate.system.pointee.drawFPS(0, 0)
    return 0
}

func myEventHandler(playdate: PlaydateAPI, event: PDSystemEvent, arg: UInt32) -> Int32 {
    savedAPI = playdate
    playdate.system.pointee.setUpdateCallback(update, nil)
    return 0
}

print("OK")

Compile:

$ swiftc -import-objc-header ./Playdate-Bridging-Header.h -I ~/Developer/PlaydateSDK/C_API/ main.swift
$ ./main
OK

That proves that the types kinda work; I was happy to even get this far.

Caveats:

  • The bridged types get pretty hairy. I tried a few things and drawFPS, being simple, was the first that actually compiled.
  • TARGET_EXTENSION has to be defined, or numerous types get ifdef-ed out and the whole thing dies. I don't know what it's meant to accomplish.

I guess the next thing to figure is how to get swiftc to spit out something the simulator can load, and how to get myEventHandler invoked?

2 Likes

Nice, this is great - I also just compilation but your approach is less hacky. Going to switch to this and see if I can get the swift bits exposed to C properly. I think that is going to be the hardest part because it's not just a simple "extern 'C'" like on other platforms. My version instead creates a proper swift library that can be imported. Currently, it is just this:

module Cpd [system] {
  header "/Users/ericlewis/Developer/PlaydateSDK/C_API/pd_api.h"
  link "pd_api"
  export *
}

A few problems though, this way is deprecated & I had to comment out the TARGET_EXTENSION stuff. I am about to board a flight but I think switching to a proper systemLibrary target will allow for passing the proper flag & then we can import the C lib in order to build out swifty api.

Less concerned with this now, more concerned with getting event handler called. Looking to these libs for some ideas too: GitHub - pd-rs/crankstart: A barely functional, wildly incomplete and basically undocumented Rust crate whose aim is to let you write Games for the Playdate handheld gaming system in Rust.

They handle the whole gamut, which we can’t until compiler support is fixed. But the way dylib works is hopefully quite similar.

I don’t think exposing the event handler directly is going to be possible, but we shall see. I can manage to get the swift code to link and load on simulator, but obviously it’s useless without anything connected.

Edit: looks like it's not being called correctly. Based on my experiments with c/swift interop - it appears that the only thing that needs to match is the symbol (I think) name. Even with mismatched definitions on c or swift side, it still works so long as the name matches. This leads me to believe that I am likely not linking correctly.

Spent some more time on this today and mostly learned that I don't really understand what SPM and swift build do. Based on what hasn't worked, my impression is that this path will indeed require building out a toolchain (like swift-embedded does) to get the linker to do something useful with the swift runtime and our entrypoint.

So, I might try cloning swift-embedded and hacking on it. This might be the quickest way to get to a statically-linked binary for the device; not so sure about the .dylib needed for the simulator (based on staring at what the C makefiles do.)

Alternatively, could stick with swiftc in combination with clang/gcc(?) to compile a minimal C wrapper and link with it. That seems like a shorter path to getting something working in the simulator with a current version of Swift, but might not get us closer to running on the device.

Neither of these exactly sounds like fun. Hopefully somebody has a better idea.

swift-embedded (or the madmachine forks of swift compiler) are basically the only ways towards running on device. I did a little hacking on swift-embedded just to get the cross tool working again, which wasn't too bad. But the toolchain being distributed isn't working and just getting that to work is important to the rest.

the dylib stuff might not be too hard, like I said - it is possible to generate an almost proper dylib. I just hadn't played much with linking.

actually appears that I can get the simulator to at least see my event handler. if I create one and expose it then build a dylib, it appears to get called. I know this by throwing a while loop in the actual function, which causes the sim to freeze. removing it... no freeze! To be even more sure, I did this:

// swiftc test.swift -emit-module -emit-library
@_cdecl("eventHandler")
public func eventHandler(_ playdate: CInt, _ event: CInt, _ arg: CInt) -> CInt {
  if event == 4 { // on pause event, hang.
    while(1 != 2) {
      // noop
    }
  }
  return 0;
}

Now, the sim should launch and work as normal until you press menu, then it will hang.

What this basically means is that the simulator is indeed calling the event handler function above. So I guess what is next is sticking the C lib in, and seeing if we can draw something.

Edit. We can draw something :smiley:

Props to @mossprescott for figuring out the swiftc thing I was lacking for the headers!

Mini-tutorial:

  1. mkdir swift-pd && cd swift-pd
  2. mkdir swift.pdx
  3. touch main.swift Playdate-Bridging-Header.h swift.pdx/pdxinfo
  4. put the following lines in swift.pdx/pdxinfo
name=Hello World Swift
author=
description=
bundleID=com.swift
imagePath=
pdxversion=10900
  1. put the following lines in Playdate-Bridging-Header.h
#define TARGET_EXTENSION 1
#include <pd_api.h>
  1. put the following lines in main.swift
var pd: PlaydateAPI!

func update(_: UnsafeMutableRawPointer?) -> CInt {
    pd.system.pointee.drawFPS(0, 0)
    return 1
}

@_cdecl("eventHandler")
public func eventHandler(_ playdate: PlaydateAPI, _ event: PDSystemEvent, _ arg: CInt) -> CInt {
  pd = playdate

  if event == kEventInit {
    playdate.system.pointee.setUpdateCallback(update, nil)
  }

  return 0;
}
  1. compile: swiftc -import-objc-header ./Playdate-Bridging-Header.h -I ~/Developer/PlaydateSDK/C_API/ main.swift -emit-module -emit-library -o swift.pdx/pdex.dylib
  2. run: open swift.pdx

Note: you will need to kill the simulator before each run.

2 Likes

A slightly more interesting program showing possible API improvements

var pd: PlaydateAPI!

func update(_: UnsafeMutableRawPointer?) -> Int32 {
  let leading = 5
  pd.drawFPS(x: leading, y: 0)
  pd.drawText("Hello World, Swift Edition!", x: leading, y: 15)
  return 1
}

@_cdecl("eventHandler")
public func eventHandler(_ playdate: PlaydateAPI, _ event: PDSystemEvent, _ arg: CInt) -> CInt {
  pd = playdate

  if event == kEventInit {
    playdate.system.pointee.setUpdateCallback(update, nil)
  }

  return 0;
}

extension PlaydateAPI {
  @discardableResult
  func drawText(_ message: String, x: Int, y: Int) -> CInt {
    self.graphics.pointee.drawText(message, message.count, kUTF8Encoding, CInt(x), CInt(y))
  }

  func drawFPS(x: Int, y: Int) {
    self.system.pointee.drawFPS(CInt(x), CInt(y))
  }
}

Edit: I now have a functional sort of swift package. can build no problem from swift build! Looking in to taking advantage of the new spm build plugins to stream line a bit. For now, it is a very simple build.sh to grab the dylib out and copy to the pdex.

Edit 2: Managed to get everything needed squished into a SwiftPM lib. Makes the public interface nicer. Sadly, no way around the swizzling, but keeps us away from C types :smiley:

import Playdate

@_dynamicReplacement(for: UpdateCallback)
func updateCallback() -> Bool {

  Playdate.shared.system.drawFPS(x: 0, y: 0)
  Playdate.shared.graphics.draw(.text("nice", x: 0, y: 20))

  return true
}

@_dynamicReplacement(for: EventCallback(event:))
func eventCallback(event: SystemEvent) {
  Playdate.shared.system.log("\(event)")
}

Alrighty, code time!

1 Like

Thanks, @ericlewis, this got me over the hump.

I had been building a .dylib in various ways but it seems if anything at all isn't right, the simulator dies with a mystifying error (for example, "Couldn't find pdz file main.pdz").

Following your lead pretty closely, I finally got it to run. And with that, I figured it was worth sharing, so I threw it up at GitHub - mossprescott/swift-pd: Bare-bones support for Playdate console apps in Swift. A work-in-progress..

And now I see you did, too :smiley:

1 Like

Yes I did! It didn't occur to me to use PDC as part of this like you did.

I was more focused on packaging and being able to use SwiftPM, which seems to be where we diverged (plus your readme is way better lol) the spm approach seems pretty sound, but there are two thing that need to be solved with it:

  • Finding the SDK path and using that in the module map for CPlaydate (how we get autogen)
  • Outputting the pdx just by running something like swift package simulator, which might be possible with the new build plugins for spm.

If those two things can be solved then it might be possible to use spm entirely, without any special setup on the consumer side.

Edit: both problems are now resolved & you can run swift package --disable-sandbox pdc --run from your project root when you have swift-playdate as a dependency.

Now I wish I could run this on device because the idiomatic swift apis are niiiiice

import Playdate

func updateCallback() -> Bool {

  Graphics.clear(with: .white)
  System.drawFPS(x: 0, y: 0)

  if System.currentButtonState == [.left, .up] {
    Graphics.draw(.text("Pressing up & left!", x: 0, y: 20))
  } else {
    Graphics.draw(.text("Time elapsed: \(System.currentTimeInterval)", x: 0, y: 20))
  }

  Graphics.drawFilledRectangle(
    Rectangle(
      x: 40,
      y: 40,
      width: 60,
      height: 30
    ),
    color: .xor
  )

  Graphics.drawLine(
    from: .zero,
    to: .init(x: 400, y: 240),
    color: .xor,
    stroke: 5
  )

  return true
}

func initialize() {
  do {
    setupDisplay()
    try setupFonts()
    try setupMenu()
  } catch {
    System.error(error.localizedDescription)
  }
}

func setupDisplay() {
  Display.isInverted = true
}

func setupFonts() throws {
  try Graphics.setFont(AshevilleSans, weight: .bold, size: .pt14)
}

enum Fonts: String, CaseIterable {
  case bold
  case light
  case italic
}

func setupMenu() throws {
  Menu.addCheckmarkItem("inverted", isOn: true) { isEnabled in
    Display.isInverted = isEnabled
  }

  Menu.addCheckmarkItem("crnk snd", isOn: true) { isEnabled in
    System.isCrankSoundEnabled = isEnabled
  }

  try Menu.addOptionItem("font", options: Fonts.allCases) { option in
    switch Fonts(rawValue: option) {
    case .bold:
      try Graphics.setFont("Asheville-Sans-14-Bold")
    case .light:
      try Graphics.setFont("Asheville-Sans-14-Light")
    case .italic:
      try Graphics.setFont("Asheville-Sans-14-Light-Oblique")
    case .none:
      break
    }
  }
}

@_dynamicReplacement(for: EventCallback(event:))
func eventCallback(event: SystemEvent) {
  if event == .initialize {
    initialize()
    System.setUpdateCallback(updateCallback)
  }
}

Messing with the swift-embedded project and I’m very close to at least getting something to link that is using the linker script for playdate. Need to figure out how to compile & link the barebones Unicode support, which is the last obstacle to spitting a build out that can be potentially loaded on device.

Edit: I think it’s as simple as compiling the Unicode lib using same toolchain to object files then linking those during the swiftc step. Will try tomorrow as it is late. The lib work I’ve done has only one reliance on foundation (won’t be avail in bare metal) which should be easy to strip out and should compile under the bare metal swift toolchain just fine. Leaving the biggest “unknown” as to wether or not my modifications to the linker script will be kosher with the device (stuffed most of the swift related calls into the heap with everything else)

Edit 1.1: random pointers to anyone else playing with swift-embedded:

  • the prepackaged toolchain is built for x86 which can cause some weirdness on M1
  • building the toolchain from scratch is pretty hard as well and I didn’t try hard enough to succeed, but this version of the compiler is unaware of M1 macs & how everyone switch from master to main.
  • since we now know everything is outdated.. so is cross, the tool that is supposed to make the build part easy :sweat_smile: I ended up sorta piecing together what it was supposed to do. I’ve also forked and fixed it, and I think it’s useless (though I’m wondering now if it’s because of how I tried to compile it at first) because compiler is so much older than the updated spm stuff.
  • you can get reasonably far using just the x86 distributed toolchain the build command is gnarly though (and can probably boil down easily)
  • this is all well & good, but it does require side loading a toolchain.
  • checking out the output bin against a real pdx bin in hopper should reveal if it may function on the device to some extent
  • the spm based Playdate lib approach will need the toolchain to support later versions of spm
  • straight swiftc version should work perfectly
  • as I sign off, just realized creating a barebones makefile for the Unicode / swift steps is probably the way to go.

Edit 2: hoorah! I have managed to get a bin out of this. definitely much more to be done, but excellent first step. Will be a challenge figuring out how to test this though without a device :laughing: the output bin is also like, 5.2mb. it's HUGE.

1 Like

Glad you're making some headway on this. I had looked at swift-embedded prior to forging ahead with just the dylib approach but gave up after making very little progress. I wish I could follow it better and contribute but hopefully that day will come.

5.2MB is big but not obviously a deal-breaker, right? That will fit in memory unless there's some limit I'm not aware of. We can work on improving the footprint down the road if we get that far.

Obviously we'll need devices in our hands to make this real. In the meantime, I suspect you could find a volunteer to try it on a device if you ask in the forums, once you have a build you think is worth trying.

Exciting stuff!

1 Like

Brief update on my progress:

I wanted to try a more interesting/realistic app requiring some non-trivial API coverage, so I ported the SpriteGame example from the SDK. That involved dealing with managing allocation (and freeing) for Bitmap, Sprite, and collision-related objects, and some strange callback shenanigans. Anyway it's all working, the Swift API is a pleasure to use, and I pushed it in case anyone wants to check it out.

As before: GitHub - mossprescott/swift-pd: Bare-bones support for Playdate console apps in Swift. A work-in-progress.

1 Like

Looking in to how SwiftWasm and AVR swift work. I’m thinking it could make sense to make changes to the compiler myself. The overall process of adding a new triple itself isn’t difficult and it appears LLVM has some level of support for thumbv7. It also may be interesting to take a look at how zig works, since it’s also llvm based.

But starting from bottom and working up may be the best way to go at this point.

I don’t think the bins I’m getting out of the compiler would work either and they’re about 2x larger than they should be.

Edit: I think one basic approach would be trying to cross compile parts of the swift runtime using the same settings as you would with typical PD games.

I have had yet another shower thought on this problem. During my exploration of swift being cross compiled for different platforms, SwiftWasm came up a few times and it’s also upstreamed into swift itself (mostly).

WASM has a pretty good performance profile and from my experience with using JS via espruino on even more limited platforms, realized that we could probably utilize an interpreter such as wasm3 (built with such limited platforms in mind) to execute SwiftWasm code.

This leaves us with creating a toolchain that is something like:
Swift -> Wasm -> armgcc or cc.

One of the larger “headaches” is WASI support, which is sort of like the syscalls of WASM. I’ve had decent success implementing syscalls for other playdate projects (like SDL2) and think it should be reasonable to port. There are also other WASM runtimes which allow fine grain disabling of WASI modules.

It’s possibly less than ideal to get swift running on a device this way but actual performance will determine if that is the case, plus, we could support even more than swift if it works well (and possibly provide just a static lib that is linked instead of fussing with a c project)

Anyway, I’m currently revamping a proper cmake toolchain and I’ll use this to build an example!

Edit: Well, it can at least run in sim. Tested using the SwiftWASM 5.5 toolchain using WAMR, which is promising enough on the porting side of things for running on device. WAMR has a route for adding new platforms.

That approach doesn't appeal to me as much as compiling/linking directly for the target platform. For one thing, won't you need a garbage collector? I know even less about WASM than I do about the Swift compiler, unfortunately, but I feel more optimistic about getting a good result from LLVM than by adding another layer.

If I get any further with the compiler/linker, I'll update here.

1 Like

It is actually quite performant surprisingly ha. I agree, I looked into SwiftWASM specifically because it will be a similar approach for running on playdate.

I’m going to attempt to fiddle with the compiler again this evening with the goal of getting the new triple added and cross-compiling parts of the runtime.

Some potential problems:

  • foundation will almost certainly not be supported at first (and never entirely) as it relies on libc we can’t use.
  • Unicode support is pretty big
  • I think parts of stdlib also require clib, so more stubbing might be necessary
  • allocators need to use the one provided by the C sdk, that shouldn’t be too problematic but it is something to note, as using simulator often masks this problem (once we are linking swift dylibs based on the pd allocator we should see changes to the malloc log we don’t see now)

Some of the better news is that once we can compile, linking shouldn’t be so bad, and things should pretty much “just work”.

Somewhat related but I think it would be way easier to compile swift for something with an RTOS, like freeRTOS or mbed. Then you wouldn’t need to deal with all the libc headaches. We can’t take that approach since we want access to the C api and I’m pretty sure the only way to get it is through the event handler.

Ninja edit: we also won’t be supporting things like concurrency or libdispatch (no GCD) anytime soon since there is no threading we can latch onto. Again, another point for the RTOSes, they can provide that. We should look toward SwiftWASM for how they handled the libc problem. WASI is similar to clib but definitely not the same.

Edit 2: I have the swift project setup with targets and presets for playdate, including targeting the correct architecture, it gets pretty far along with trying to cross compile the runtime but I have quite a bit more work to do in order to ensure that all the right tools are being used. On a side note, it appears we can likely include the playdate c api as part of the stdlib, so when using this toolchain you will get that out of the box! I also have plenty of stubbing / things to disable. WASI is helpful in that we have somewhat similar limitations, and referencing embedded-swift + the madmachine repos is proving fruitful as well. Ideally, this won’t become as easily defunct as previous attempts for providing this functionality.

Edit 3: making it a little over halfway through compiling the runtime, the new concurrency changes are making a lot of assumptions about the existence of threads. There are levers to turn most of that off, but it’s not used everywhere it seems.

Edit 4: I’m able to get a substantial amount of the runtime to compile & link but there are bugs in the swift side of compiling stdlib. Went too far down the rabbit hole trying to keep everything within the swift build scripts themselves. Going to revert my edits to the scripts and instead attempt to build and link standalone, with the intention of putting the scripts backs. Most of the edits in source can stay, they’re straight forward and shouldn’t change. Some of the checks can be cleaned up (the messy script problem started seeping into everything), but otherwise it should be good. A big problem I was having with the baremetal approach to scripting was how it glommed on to the other Apple / Darwin based SDKs in order to get similar treatment. It’s an extremely brittle approach as these build scripts change between minor versions of swift in a pretty substantial way. There is not much work that actually is to be done in order to support a new platform, it’s figuring out the right incantations in the build script that is hard.

Edit 5: went back to the approach that adding WASI support took, including adding playdate as a proper OS to llvm. Having stared at all of this code long enough and seeing approaches people have taken inside and outside of the swift project, this one seems to most manageable to get working, further, it should make keeping up with a fork easier. Most of the other attempts at this seem to alter swift in such a way that it’s very hard to keep in sync with upstream. It could also be worth upstreaming this code, with the biggest difference from the other embedded attempts being that we aren’t exactly targeting baremetal. This means less change in general to the overall swift project, is actually more correct, and doesn’t open the can of worms that attempting to bring true baremetal support would. Another benefit would be the folks who keep refactoring the build scripts would need to do (most) that work for us, which is also the bulk of the work typically. More challenging is creating an environment for running stdlib tests, which would be required for upstream, challenging because it needs to be run on qemu or the like in a semi-hosted fashion.

I have successfully compiled a single piece of runtime!

/Users/ericlewis/developer/swift-toolchain-exp/host-build/Ninja-Release/llvm-macosx-arm64/bin/clang++ --target=thumbv7em-unknown-playdate -DGTEST_HAS_RTTI=0 -DLLVM_DISABLE_ABI_BREAKING_CHECKS_ENFORCING=1 -DSWIFT_INLINE_NAMESPACE=__runtime -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/Users/ericlewis/developer/swift-toolchain-exp/target-build/swift-stdlib-playdate-thumbv7em/stdlib/public -I/Users/ericlewis/developer/swift-toolchain-exp/swift/stdlib/public -I/Users/ericlewis/Developer/swift-toolchain-exp/swift/stdlib/include -I/Users/ericlewis/developer/swift-toolchain-exp/target-build/swift-stdlib-playdate-thumbv7em/include -I/Users/ericlewis/Developer/swift-toolchain-exp/swift/include -I/Users/ericlewis/developer/swift-toolchain-exp/target-build/llvm-playdate-thumbv7em/include -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wdelete-non-virtual-dtor -Wno-comment -fdiagnostics-color -DOBJC_OLD_DISPATCH_PROTOTYPES=0 -O3 -DNDEBUG -fvisibility=hidden -fvisibility-inlines-hidden  -fno-exceptions -fno-rtti -Werror=gnu -Werror=c++98-compat-extra-semi -DswiftCore_EXPORTS -DSWIFT_SUPPORT_OLD_MANGLING=0 -DSWIFT_STDLIB_HAS_TYPE_PRINTING -DSWIFT_TARGET_LIBRARY_NAME=swiftDemangling -DSWIFT_RUNTIME -target thumbv7em-unknown-playdate -O2 -g0 -DNDEBUG -I/ -DSWIFT_OBJC_INTEROP=0 -DSWIFT_LIBRARY_EVOLUTION=0 -DSWIFT_STDLIB_SUPPORT_BACK_DEPLOYMENT -DSWIFT_ENABLE_REFLECTION -DSWIFT_STDLIB_HAS_DLADDR -DSWIFT_STDLIB_HAS_DARWIN_LIBMALLOC=1 -DSWIFT_STDLIB_HAS_STDIN -DSWIFT_STDLIB_HAS_ENVIRON -DSWIFT_STDLIB_HAS_LOCALE -DSWIFT_STDLIB_SINGLE_THREADED_RUNTIME -DSWIFT_RUNTIME_OS_VERSIONING -DSWIFT_STDLIB_SHORT_MANGLING_LOOKUPS -DSWIFT_STDLIB_ENABLE_VECTOR_TYPES -DSWIFT_STDLIB_SUPPORTS_BACKTRACE_REPORTING -D SWIFT_STDLIB_ENABLE_UNICODE_DATA -MD -MT stdlib/public/CMakeFiles/swiftDemangling-playdate-thumbv7em.dir/__/__/lib/Demangling/Context.cpp.o -o Context.cpp.o -c /Users/ericlewis/developer/swift-toolchain-exp/swift/lib/Demangling/Context.cpp -I/Users/ericlewis/Downloads/gcc-arm-none-eabi-10.3-2021.10/usr/include/c++/10.3.1 -I/Users/ericlewis/Downloads/gcc-arm-none-eabi-10.3-2021.10/usr/include/c++/10.3.1/arm-none-eabi --sysroot=/Users/ericlewis/Downloads/gcc-arm-none-eabi-10.3-2021.10

Yes, this is using the wrong arm toolchain but it also works with the playdate distributed one, and yes some of the flags are most certainly incorrect. There are also some changes that I made to the folder in order for this to work, such as moving c++ bits to the top level and hacking on this to include newlib. Another noteworthy change is this is not using arm-none-eabi-gcc, but rather using clang and LLVMs support for the thumb architecture (which is considered experimental). Changing the compiler used is definitely a more complex task so my first effort is going to be seeing if what clang outputs is usable on device. The thesis mentions this as a possible path forward and instead decides that it would be easier use the entire toolchain provided by arm. I have a feeling this would most likely impact the linker step (I have only compiled, not linked yet), but that should be resolvable since WASI also uses it's own linker. We could indeed change any of this behavior in our PlaydateToolChains as well and if we need to switch compilers / linkers / etc, it would all happen there & in the driver. Getting the right include flags in place is the next step so I can continue compiling the rest of the runtime. It is easy enough to do so in a hacky way, so I may attempt that first, then move it to the ToolChains file (there is a non-trivial amount of work to creating such a file). Another worthy bit of investigation is around the swift stdlib freestanding flag, which appears to be helpful when you don't have a clib, (we sorta do, in newlib, but it needs to be stubbed / some features don't work)

Edit: another bit of consideration to have is that we are needing to use an entirely new swift toolchain, which becomes slightly problematic when we consider how compilation works now. I am unsure if we are able to completely alter the compiler behavior based on wether or not we are creating an executable or dynamic lib. This may require investigation into how building for iOS for sim or device works. It could very well be that we simply change the SDK we are pointed at to one that supports x86/aarch64, but again, I am not sure. For now the workaround is to simply switch toolchains depending on what you are targeting. It is possible that we need to alter this behavior in spm.

Aside: @mossprescott do you think we should move the dev progress of these things to this thread: Using the swift programming language on Playdate - #11 by ericlewis, since it is technically in dev by us.

2 Likes