Page 1 of 2

PureBasic + SDL + Mac ...

Posted: Sat Jul 12, 2014 8:25 pm
by kenmo
Lately I have been playing with the SDL library imported into PureBasic (SDL 2.0.3 and SDL2_image, maybe in the future SDL2_mixer).

(You might ask: why bother with SDL? PureBasic already does cross-platform video, graphics, audio, keyboard, mouse, joystick... Well (A) it has some nice extras, like more Joystick functions and the GameController subsystem which translates many different gamepads to a standard XBox-like layout... also (B) I just want to learn SDL and practice importing libraries into PB!)


I just finished my first PB + SDL project, a small game for Windows and Mac. On Windows, the process was easy: import SDL functions, build the executable, package it with the necessary DLLs.

But Mac OSX doesn't use DLLs, it uses Frameworks, and the SDL2 runtime is packaged as a Disk Image (.dmg) which must be "mounted" and then installed to /Library/Frameworks. This is new and confusing to me!

I guess my ultimate question is: What is the "best" way to release a PureBasic Mac project that uses external Frameworks like SDL? I see 5 options:

1. Release the app WITHOUT the runtime, prompt the user if they need to download + install it
2. Release the app with the runtime, prompt the user if they need to install it
3. Release the app with the runtime, automatically install it if missing
4. Release the app with the runtime, load it from the local directory like a DLL, no installation to /Library/Frameworks
5. Statically link the runtime, no external framework needed


Some thoughts about each option:

1. Easiest method for me, but biggest annoyance for the user (download, mount, install)
2. Maybe the best overall method
3. I don't know if a PB program can auto-install a Framework, there might be permission issues, and you can't just copy a DMG into "Frameworks"
4. Again, I don't know how this works on Mac. I don't think you can just drop a DMG in a folder and expect it to do anything.
5. I have no idea how to statically link an open-source library written in C to a PureBasic Mac project... but I am willing to learn!


Any ideas, PureBasic and Mac and SDL experts? :?: Thanks for reading!

Re: PureBasic + SDL + Mac ...

Posted: Sat Jul 12, 2014 8:48 pm
by wilbert
Isn't there a .dylib (similar to a windows .dll) you can use ?

Re: PureBasic + SDL + Mac ...

Posted: Sat Jul 12, 2014 9:02 pm
by kenmo
I don't know if there is a dylib... The SDL runtime for Mac is a DMG download, but I am on Windows right now so I can't mount it and see if there is a dylib somewhere inside.

SDL download page is here: http://www.libsdl.org/download-2.0.php

If there is a SDL dylib available, would I just put it in my PB game's directory and it would use it "automatically", like placing the right DLLs in your executable folder on Windows? (Furthermore, would I put it in the .app's parent directory, or the internal Contents/MacOS/ or Contents/Resources/ directory?? I am relatively new to OSX.)

Re: PureBasic + SDL + Mac ...

Posted: Sat Jul 12, 2014 9:06 pm
by J. Baker
You can make a "Frameworks" folder within your app and put the "SDL.Framework" in there. Then all you have to do is link from it there. It's only 1.4MB so it won't add much to your app. ;)

Re: PureBasic + SDL + Mac ...

Posted: Mon Jul 14, 2014 1:11 am
by kenmo
Is it that simple? I want to try that on a Mac ASAP. (I thought it had to be loaded from /Library/Frameworks or ~/Library/Frameworks )

Now, if I put the .Framework inside my app, do I still "Import" it in my PB code and call it like native functions, or do I need to use OpenLibrary / CallFunction ? ... Eh I guess I will find out by trying :)

Re: PureBasic + SDL + Mac ...

Posted: Mon Jul 14, 2014 1:12 am
by J. Baker
kenmo wrote:Is it that simple? I want to try that on a Mac ASAP. (I thought it had to be loaded from /Library/Frameworks or ~/Library/Frameworks )

Now, if I put the .Framework inside my app, do I still "Import" it in my PB code and call it like native functions, or do I need to use OpenLibrary / CallFunction ? ... Eh I guess I will find out by trying :)
Just using the "Import" will do. Just make sure the import link is within your app. ;)

Re: PureBasic + SDL + Mac ...

Posted: Mon Jul 14, 2014 2:37 am
by jack
just out of curiosity I downloaded the SDL source and from the terminal you can build a dylib and a static lib, but the size of the static lib is over four times as that of the dylib, makes me wonder.
btw, the source also includes project files for Xcode, the dmg builds with warnings.

Re: PureBasic + SDL + Mac ...

Posted: Mon Jul 14, 2014 5:38 pm
by kenmo
@J, have you successfully imported a library from inside a .app before? I can't get it to work :? Maybe I'm doing something wrong, or maybe there's something different about the SDL specifically. Maybe I'll put together a test project, and post it here.

@jack, I think I read that the official SDL 2.0.3 release has some accidental build issues which have since been fixed. Also I found an interesting note in the SDL OSX readme:
But beware! That is only part of the story! With the above, you end up with
a bare bone .app bundle, which is double clickable from the Finder. But
there are some more things you should do before shipping your product...

1) The bundle right now probably is dynamically linked against SDL. That
means that when you copy it to another computer, *it will not run*,
unless you also install SDL on that other computer. A good solution
for this dilemma is to static link against SDL. On OS X, you can
achieve that by linking against the libraries listed by
sdl-config --static-libs
instead of those listed by
sdl-config --libs
Depending on how exactly SDL is integrated into your build systems, the
way to achieve that varies, so I won't describe it here in detail
From: https://hg.libsdl.org/SDL/file/tip/README-macosx.txt

Re: PureBasic + SDL + Mac ...

Posted: Mon Jul 14, 2014 5:51 pm
by J. Baker
I've just seen it done that way by other app/games. If you put together a test project, I'll gladly test it out and see what's going on. ;)

Re: PureBasic + SDL + Mac ...

Posted: Tue Jul 15, 2014 12:49 am
by kenmo
You could try messing around with this: <URL>

Includes a test PB program, Windows + Mac runtimes, a "fresh" built .app and a copy of that .app with the SDL Framework thrown in every possible sub-folder...

I can get PB Mac to BUILD the .app by putting the Framework right in the source's folder, but I cannot find a way to RUN the .app unless I drop SDL in the system's Frameworks folder :?:

(Of course this is just thinking ahead for releasing a PB+SDL project. For developing, of course I would put it in /Library/Frameworks, that way I can directly run my Mac program from the IDE -- since overwriting the .app every time would delete any internal Framework files!)

Re: PureBasic + SDL + Mac ...

Posted: Tue Jul 15, 2014 2:15 am
by J. Baker
It appears that only a literal string can be used after Import C. So using something like GetHomeDirectory() can not be used. Therefor we can't get the apps sub-folder location. Maybe there's a Cocoa method that can be used but not sure at the moment.

The next best thing I can think of is to include the framework as binary. Then at startup check if SDL2 is installed. If not, dump it to "/Library/Frameworks".

I'll check this out a little more to see if there's an alternative method. ;)

Re: PureBasic + SDL + Mac ...

Posted: Tue Jul 15, 2014 6:05 am
by wilbert
If a Framework contains Cocoa classes, you can load it dynamically using the NSBundle class and use those classes inside the Framework afterwards.

Re: PureBasic + SDL + Mac ...

Posted: Tue Jul 15, 2014 6:59 am
by Danilo
Copy SDL2.framework into /Library/Frameworks on your Mac. Your code works from within the PB IDE then.

To make a standalone .app, copy SDL2.framework into your app. Put it into folder:

Code: Select all

your.app/Contents/Frameworks/
Now run the following command on the command line (same directory where your .app is):

Code: Select all

install_name_tool -add_rpath @executable_path/../Frameworks ./SDL_Test.app/Contents/MacOS/SDL_Test
This adds the .app internal 'Frameworks' directory to the search path for frameworks.

Now test it is working:

Code: Select all

./SDL_Test.app/Contents/MacOS/SDL_Test
Works fine here, shows a green window for 2 seconds.

To Import and include .dylib, see: Import : EndImport - path?

Re: PureBasic + SDL + Mac ...

Posted: Tue Jul 15, 2014 7:02 am
by wilbert
Another way would be using the PB library functions but that probably is not what you want.

Code: Select all

PrototypeC.i _SDL_Init(flags.l)
PrototypeC _SDL_Quit()
PrototypeC.i _SDL_CreateWindowAndRenderer(width.i, height.i, window_flags.l, *pWindow, *pRenderer)
PrototypeC _SDL_DestroyRenderer(*renderer)
PrototypeC _SDL_DestroyWindow(*window)
PrototypeC.i _SDL_SetRenderDrawColor(*renderer, r.a, g.a, b.a, a.a)
PrototypeC.i _SDL_RenderClear(*renderer)
PrototypeC _SDL_RenderPresent(*renderer)

If OpenLibrary(0, "SDL2.framework/SDL2")
  Global SDL_Init._SDL_Init = GetFunction(0, "SDL_Init")
  Global SDL_Quit._SDL_Quit = GetFunction(0, "SDL_Quit")
  Global SDL_CreateWindowAndRenderer._SDL_CreateWindowAndRenderer = GetFunction(0, "SDL_CreateWindowAndRenderer")
  Global SDL_DestroyRenderer._SDL_DestroyRenderer = GetFunction(0, "SDL_DestroyRenderer")
  Global SDL_DestroyWindow._SDL_DestroyWindow = GetFunction(0, "SDL_DestroyWindow")
  Global SDL_SetRenderDrawColor._SDL_SetRenderDrawColor = GetFunction(0, "SDL_SetRenderDrawColor")
  Global SDL_RenderClear._SDL_RenderClear = GetFunction(0, "SDL_RenderClear")
  Global SDL_RenderPresent._SDL_RenderPresent = GetFunction(0, "SDL_RenderPresent")
EndIf

If (SDL_Init($20) = 0)
  If (SDL_CreateWindowAndRenderer(640, 480, 0, @*win, @*ren) = 0)
    SDL_SetRenderDrawColor(*ren, 0, 255, 0, 255)
    SDL_RenderClear(*ren)
    SDL_RenderPresent(*ren)
    Delay(2000)
    SDL_DestroyRenderer(*ren)
    SDL_DestroyWindow(*win)
  EndIf
  SDL_Quit()
EndIf

Re: PureBasic + SDL + Mac ...

Posted: Tue Jul 15, 2014 5:20 pm
by kenmo
Danilo, does that mean the end-user would have to run that commandline? A lot of game players would hate that... Also I have read about conflicting Framework paths for example if SDL is in their Library folder plus a local path.

Using OpenLibrary() and Prototypes leads to an uglier include file, but in the end... does it matter? I imagine performance is the same for Prototype calls vs a Framework/dylib link?

Thanks all. Hmmm, I've got some experimenting to do. Of course as I said this is just preparation for future projects.