flareteam / flare-engine

Free/Libre Action Roleplaying Engine (engine only)
http://flarerpg.org/
GNU General Public License v3.0
1.1k stars 186 forks source link

Mac OS X maintainer #1583

Closed dorkster closed 2 years ago

dorkster commented 6 years ago

Opening this thread for anyone that would like to create the .dmg files for Mac OS X. This includes both the engine and the engine+game files.

tvleavitt commented 6 years ago

What's involved here? I've got a fair amount of experience compiling software as a Unix/Linux Sysadmin over the last quarter century.

dorkster commented 6 years ago

I know practically nothing about Mac OS development. Maybe @clintbellanger can at least explain, how 0.19 was built and packaged. I suspect the most notable change for the current engine would be swapping out SDL 1.2 for SDL 2.

I don't know if a dmg is just a plain archive, or if there's more to it. If the files that would need to be added are similar to the Windows zips, the dmgs should look like this:

Engine

flare executable
SDL 2 libraries, akin to Windows .dlls
COPYING
CREDITS.engine.txt
README.engine.md
RELEASE_NOTES.txt
mods/mods.txt
mods/default/

Engine + Game

(everything from the engine)
README.md (part of flare-game)
CREDITS.txt (part of flare-game)
mods/fantasycore/ (part of flare-game)
mods/empyrean_campaign/ (part of flare-game)
mods/centered_statbars/ (part of flare-game)
tvleavitt commented 6 years ago

Hmm... well, I was able to pull the source from GitHub, and successfully build and run the code (0.95.19), and creating a DMG looks to be pretty trivial, so I suspect all I need is a list of what should be contained in the DMG and I'll be good to go.

clintbellanger commented 6 years ago

Maybe you can grab a prebuilt copy of 0.18 or 0.19 to see how the DMG was structured. Besides all those data files listed above, I remember needing to put a copy of the main Libraries / Frameworks in the DMG. Version 2 of these:

clintbellanger commented 6 years ago

I always cobbled the DMG together manually. If you (or anyone) knows how to make a script that will create the DMG perfectly each time, we'd love to add it to this repo.

tvleavitt commented 6 years ago

I'll take a look at the previous DMG. Should I build it based on the current release, 0.95.19?

dorkster commented 6 years ago

Since we're finished the first week of our 2-week testing period, I've bumped the version to 0.96 for both engine and game. So please use that tag.

dorkster commented 6 years ago

Today is the last day of our testing period. The original plan was to tag 1.0 tomorrow and get the binaries ready, However, @gunchleoc asked me for an extension to finish his translation.

So @tvleavitt, if I tagged 1.0 on Monday, do you think you could get the DMG files made and sent to me the same day? I think we will release no matter what on Monday, but I would like the Mac OS release to be simultaneous.

dorkster commented 6 years ago

@gunchleoc finished his translation, so I've tagged 1.0 tonight. We'll be releasing tomorrow, so getting DMGs for the engine and game soon would be much appreciated.

tvleavitt commented 6 years ago

I'll work on this tomorrow afternoon, then. Will provide update around 5 p.m. or so.

Edit: I took a peek at this, just before going to bed.

So, this is what is in the 0.19 Engine + Alpha Demo DMG:

COPYING CREDITS.txt Flare.app README RELEASE_NOTES.txt (plus misc. OS X system files that I doubt are relevant)

I see no SDL or other libraries. I see no "mods" directory.

The executable produced by running cmake / make is "flare". Not Flare.app.

My main question at this point would be, how do I create a .app file, and what would go into it? Or do we want to create a .pkg file instead, and have people run that, instead of dragging and dropping the monolithic executable?

tvleavitt commented 6 years ago

I'm finished with my morning client; am free most of the day, I'll try and figure this out, but guidance would speed up the process considerably, I suspect.

dorkster commented 6 years ago

I think the Flare.app file is a package that contains

tvleavitt commented 6 years ago

Got it. See that now. Just have to figure out how to create the package.

tvleavitt commented 6 years ago

Building Info.plist.

What do I put for these (optional)? No values in previous Info.plist.

LSMinimumSystemVersion (Minimum system version) The minimum version of macOS required for this application to run. The value for this key is a string of the form n.n.n where each n is a number representing either the major or minor version number of macOS that is required. For example, the value 10.1.5 would represent macOS v10.1.5.
NSHumanReadableCopyright (Copyright (human-readable)) The copyright notice for the application. This is a human readable string and can be localized by including the key in an InfoPlist.strings file in your language-specific project directories.

Have the following changed?

NSMainNibFile (Main nib file base name) The nib file to load when the application is launched (without the .nib filename extension). The main nib file is an Interface Builder archive containing the objects (main window, application delegate, and so on) needed at launch time.
NSPrincipalClass (Principal class) The entry point for dynamically loaded Objective-C code. For an application bundle, this is almost always the NSApplication class or a custom subclass.

Here's what's there now:

    <key>NSMainNibFile</key>
<string>SDLMain</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>

I'm building the package by hand (will turn it into a script), trying to figure out how to do it via XCode seems like a lot of overhead for a one-off project like this.

https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW1

dorkster commented 6 years ago

I think @clintbellanger used XCode to do the old builds, so I don't know much about those fields. I would leave the first blank and if we get any old Mac users complaining they can't run the game. NSMainNibFile is probably the same as it was before.

tvleavitt commented 6 years ago

InfoPlist.strings from 0.19

/ Localized versions of Info.plist keys /

CFBundleName = "Flare"; CFBundleShortVersionString = "Flare version 0.1"; CFBundleGetInfoString = "Flare version 0.1, Copyright 2013 Clint Bellanger."; NSHumanReadableCopyright = "Copyright 2013 Clint Bellanger.";

Would this update to

/ Localized versions of Info.plist keys /

CFBundleName = "Flare"; CFBundleShortVersionString = "Flare version 1.0"; CFBundleGetInfoString = "Flare version 1.0, Copyright 2018 Clint Bellanger."; NSHumanReadableCopyright = "Copyright 2018 Clint Bellanger.";

?

dorkster commented 6 years ago

Yes. Looks like it was made for the first Mac OS build and then forgotten about.

tvleavitt commented 6 years ago

I think I have everything. I looks like I have to manually create the SDL_xxxxx.framework files, working on that now. Then, obviously, testing.

tvleavitt commented 6 years ago

Great; SDL wiki page says I'm right. I don't see SDL in either /Library/Frameworks or ~/Library/Frameworks. I'm going to see if I can download them from somewhere... manually assembling these seems... sketchy.

http://overooped.com/post/42240519/properly-bundling-frameworks-in-your-application

tvleavitt commented 6 years ago

I downloaded DMG files for the appropriate SDL libraries and copied them over.

I don't see an application icon file in the original Flare.app build. I'm building a Flare.app and Flare-engine.app folder for Flare and Flare-engine, along with associated DMG files. What do I do here? Like, 1.0 should have an icon. I can repurpose something else if I'm pointed to it.

The Application Icon File

One special resource that belongs in your top-level Resources directory is your application icon file. By convention, this file takes the name of the bundle and an extension of .icns; the image format can be any supported type, but if no extension is specified, the system assumes .icns.

dorkster commented 6 years ago

We have an SVG icon. You may need to convert it: https://github.com/clintbellanger/flare-engine/blob/master/distribution/flare_logo.svg

tvleavitt commented 6 years ago

This is what I get when I try to launch the Flare.app at this point.

flare error ss

dorkster commented 6 years ago

Where did you put the mods folder in the Flare.app? It might need to be alongside the actual executable.

tvleavitt commented 6 years ago

Resources/mods as in original 0.19 DMG Flare.app package.

dorkster commented 6 years ago

If you're building with cmake you may need to add -DDATADIR=Resources. If you're not using cmake, you'll need to define DATA_INSTALL_DIR. In our cmake file, DATA_INSTALL_DIR is set to ${CMAKE_INSTALL_PREFIX}/${DATADIR}.

tvleavitt commented 6 years ago

Moved it to MacOS (which would violate the specification as described by Apple); same error. Can launch from compile directory. Manually launching binary on command linbe from within Flare.app/MacOS folder yields same:

2018-03-12 17:15:57.844 Flare[30948:1116076] INFO: Flare 1.0 (Mac OS X) 2018-03-12 17:15:58.605 Flare[30948:1116076] ERROR: ModManager: Mod "fantasycore" not found, skipping 2018-03-12 17:15:58.606 Flare[30948:1116076] ERROR: ModManager: Mod "empyrean_campaign" not found, skipping 2018-03-12 17:15:58.606 Flare[30948:1116076] INFO: Active mods: 2018-03-12 17:15:58.606 Flare[30948:1116076] ERROR: main: Could not find the default mod in the following locations: 2018-03-12 17:15:58.606 Flare[30948:1116076] ERROR: /Users/tvleavitt/.local/share/flare/mods/ 2018-03-12 17:15:58.606 Flare[30948:1116076] ERROR: A copy of the default mod is in the "mods" directory of the flare-engine repo. 2018-03-12 17:15:58.607 Flare[30948:1116076] ERROR: The repo is located at: https://github.com/clintbellanger/flare-engine 2018-03-12 17:15:58.607 Flare[30948:1116076] ERROR: Try again after copying the default mod to one of the above directories. Exiting.

tvleavitt commented 6 years ago

Yes, using cmake. I'll try rebuilding with specified parameter.

tvleavitt commented 6 years ago

Ran "cmake -DDATADIR=Resources" in flare-engine, then ran make. No joy.

tvleavitt commented 6 years ago

Here's the structure:

Flare.app/Contents/MacOS/Flare (executable) Flare.app/Contents/Resources/mods/

So, maybe it needs to be -DDATADIR=../Resources instead? Will try that.

Edit: that didn't work either. :/ Same error message. I'm thinking this is hardcoded somewhere, in a way different from 0.19?

dorkster commented 6 years ago

I don't think the paths are any different than 0.19. Maybe @clintbellanger can enlighten us as to what to use for DATADIR.

dorkster commented 6 years ago

Crap! We changed it so that ./mods/ is preferred over the install directory after people had trouble running locally compiled versions. Very likely that needs to be fixed for the Mac version to work.

Edit: maybe not, we only use ./mods/ if it exists, which it shouldn't. Unless it's picking up a mods folder outside the Flare.app.

clintbellanger commented 6 years ago

I don't remember doing anything to handle this specifically. As if the Flare.app/Contents/Resources/ folder was automatically the "working directory" when running the app. But I built using an old version of xcode and not cmake. Maybe there's a setting for that? E.g. some kind of manifest or settings file in the DMG?

dorkster commented 6 years ago

@tvleavitt Is there a mods/ folder in the same folder as Flare.app? It might be picking that one up.

Also, just to be sure, could you list the contents of Flare.app/Contents/Resources/mods/?

dorkster commented 6 years ago

We should try to get an idea of what game sees in data folder. Try adding the following to the end (after line 151) of PlatformSetPaths() in src/PlatformLinux.cpp:

    std::vector<std::string> dir_names;
    getDirList(PATH_DATA, dir_names);
    for (size_t i = 0; i < dir_names.size(); ++i) {
        logInfo("PATH_DATA contains: %s/", dir_names[i].c_str());
    }

Then either run the app from the Terminal or check ~/.config/flare/flare_log.txt for the output.

tvleavitt commented 6 years ago

No mods directory in the directory where I'm assembling Flare.app and Flare-engine.app.

Here's the directory structure of Flare.app

flare contents listing

dorkster commented 6 years ago

The app directory structure looks correct. Have you tried what I suggested here yet?

tvleavitt commented 6 years ago

Oh, I missed that the comment was directed at me. O.K. I'll make that edit and report back.

tvleavitt commented 6 years ago

Running this on command line as ./flare from within "flare-game" after adding text. It's clearly looking in the current directory.

2018-03-12 20:29:38.581 flare[33373:1205706] INFO: PATH_DATA contains: .git/ 2018-03-12 20:29:38.582 flare[33373:1205706] INFO: PATH_DATA contains: art_src/ 2018-03-12 20:29:38.582 flare[33373:1205706] INFO: PATH_DATA contains: CMakeFiles/ 2018-03-12 20:29:38.582 flare[33373:1205706] INFO: PATH_DATA contains: distribution/ 2018-03-12 20:29:38.582 flare[33373:1205706] INFO: PATH_DATA contains: mods/ 2018-03-12 20:29:38.582 flare[33373:1205706] INFO: PATH_DATA contains: tiled/

Let's see what happens when I run it via Flare.app. [Edit: moved here for clarity, output is below.] Clicking on Flare.app in Finder yields this, it's running with / as it's working directory; that doesn't seem right? Edit: it appears this is the expected behavior from an app launched in Finder.

INFO: PATH_DATA contains: .Trashes/ INFO: PATH_DATA contains: .vol/ INFO: PATH_DATA contains: Applications/ INFO: PATH_DATA contains: bin/ INFO: PATH_DATA contains: cores/ INFO: PATH_DATA contains: dev/ INFO: PATH_DATA contains: Developer/ INFO: PATH_DATA contains: etc/ INFO: PATH_DATA contains: home/ INFO: PATH_DATA contains: Incompatible Software/ INFO: PATH_DATA contains: Library/ INFO: PATH_DATA contains: net/ INFO: PATH_DATA contains: Network/ INFO: PATH_DATA contains: opt/ INFO: PATH_DATA contains: private/ INFO: PATH_DATA contains: sbin/ INFO: PATH_DATA contains: System/ INFO: PATH_DATA contains: tmp/ INFO: PATH_DATA contains: Users/ INFO: PATH_DATA contains: usr/ INFO: PATH_DATA contains: var/ INFO: PATH_DATA contains: Volumes/

tvleavitt commented 6 years ago

Locating Items in Your App Bundle

Apps that need to locate resource files inside their bundle directory (or inside another known bundle) must do so using an NSBundle object. Bundles eliminate the need for your app to remember the location of individual files by organizing those files in a specific way. The methods of the NSBundle class understand that organization and use it to locate your app’s resources on demand. The advantage of this technique is that you can generally rearrange the contents of your bundle without rewriting the code you use to access it. Bundles also take advantage of the current user’s language settings to locate an appropriately localized version of a resource file.

The following code shows how to retrieve a URL object for an image named MyImage.png that is located in the app’s main bundle. This code determines only the location of the file; it does not open the file. You would pass the returned URL to a method of the NSImage class to load the image from disk so that you could use it.

NSURL* url = [[NSBundle mainBundle] URLForResource:@"MyImage" withExtension:@"png"];

For more information about bundles, including how to locate items in a bundle, see Bundle Programming Guide. For specific information about loading and using resources in your app, see Resource Programming Guide.

https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html

dorkster commented 6 years ago

Let's see what happens when I run it via Flare.app. 2018-03-12 20:29:38.582 flare[33373:1205706] INFO: PATH_DATA contains: mods/

Does Flare.app still not work in this instance? I suppose that would make sense, as I don't think apps are supposed to read outside of their own internal structure.

Interesting about it looking at / for data. PATH_DATA defaults to ./ when nothing can be found, so I guess the default working directory of apps is /.

https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/AccessingFilesandDirectories/AccessingFilesandDirectories.html

I wonder if XCode was replacing standard library functions with those automatically?

tvleavitt commented 6 years ago

Edited comment for clarity. I'm unfamiliar enough with this stuff to not have any certainty as to whether this is a function of the Info.plist not being properly specified, an issue with how the PATH is being defined, or a side effect of OS X 10.12 security.

This from 2014:

The POSIX way to change the working directory is:

include

int chdir(const char *path);

To discover the path of the application bundle, you use Core Foundation's CFBundle API. So, something like this:

include

include <CoreFoundation/CoreFoundation.h>

... CFURLRef url = CFBundleCopyResourcesDirectoryURL(CFBundleGetMainBundle()); char path[PATH_MAX]; if (!CFURLGetFileSystemRepresentation(url, true, (UInt8)path, sizeof(path)) || chdir(path) != 0) / handle error */; CFRelease(url);

https://stackoverflow.com/questions/24419799/set-working-directory-in-c-code-on-osx

tvleavitt commented 6 years ago

Do we care about Code Signing? I don't have a current Apple Developer account.

dorkster commented 6 years ago

I don't think we signed the old versions, so don't worry about that.

dorkster commented 6 years ago

Okay, I tried adding the CFBundle stuff to PlatformLinux.cpp: https://gist.github.com/dorkster/33995e69af5da6314a0cf273c10e9505

Hopefully that at least compiles.

tvleavitt commented 6 years ago

I pulled this down directly, rather than using Git, since I'd already edited that file.

In file included from /Users/tvleavitt/appdev/flare-engine/src/main.cpp:60: In file included from /Users/tvleavitt/appdev/flare-engine/src/PlatformLinux.cpp:37: In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:43: In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h:77: /usr/include/MacTypes.h:538:8: error: redefinition of 'Point' struct Point { ^ /Users/tvleavitt/appdev/flare-engine/src/Utils.h:37:7: note: previous definition is here class Point { ^ In file included from /Users/tvleavitt/appdev/flare-engine/src/main.cpp:60: In file included from /Users/tvleavitt/appdev/flare-engine/src/PlatformLinux.cpp:37: In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CoreFoundation.h:43: In file included from /System/Library/Frameworks/CoreFoundation.framework/Headers/CFBase.h:77: /usr/include/MacTypes.h:544:8: error: redefinition of 'Rect' struct Rect { ^ /Users/tvleavitt/appdev/flare-engine/src/Utils.h:52:7: note: previous definition is here class Rect { ^ /Users/tvleavitt/appdev/flare-engine/src/main.cpp:240:15: warning: implicit conversion changes signedness: 'int32_t' (aka 'int') to 'Uint32' (aka 'unsigned int') [-Wsign-conversion] SDL_Delay(delay_ms);


2 warnings and 2 errors generated.
make[2]: *** [CMakeFiles/flare.dir/src/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/flare.dir/all] Error 2
tvleavitt commented 6 years ago

NameSpace conflict with OS X System headers?

dorkster commented 6 years ago

Argh, that's frustrating. Should be fixable by wrapping it in a new namespace:

#ifdef __APPLE__
namespace AppleCore {
#include <CoreFoundation/CoreFoundation.h>
}
#endif

#ifdef __APPLE__
    logInfo("Platform: Using Mac OS .app prefix for PATH_DATA");
    AppleCore::CFURLRef url = AppleCore::CFBundleCopyResourcesDirectoryURL(AppleCore::CFBundleGetMainBundle());
    char base_path[PATH_MAX];
    if (AppleCore::CFURLGetFileSystemRepresentation(url, true, (AppleCore::UInt8*)base_path, sizeof(base_path))) {
        PATH_DATA = std::string(base_path) + "/"; // TODO do we need trailing slash here?
    }
    AppleCore::CFRelease(url);

    return;
#endif
tvleavitt commented 6 years ago

That fixed it. App runs, loads.

I can ship off my hand edited copy with your changes, I can pull down from Git and move my master past 1.0, etc. Let me know. Still have to create the DMG images.

Note: just FYI, the first time the app runs, it throws non-critical errors about missing files:

flare[58654:2186642] ERROR: FileParser: Could not open text file: /Users/tvleavitt/.local/share/flare/saves/empyrean/stash.txt 2018-03-02 20:01:36.923 flare[58654:2186642] ERROR: SaveLoad: Unable to open /Users/tvleavitt/.local/share/flare/saves/empyrean/stash.txt! 2018-03-02 20:01:36.932 flare[58654:2186642] ERROR: FileParser: Could not open text file: /Users/tvleavitt/.local/share/flare/saves/empyrean/stash.txt 2018-03-02 20:01:36.932 flare[58654:2186642] ERROR: SaveLoad: Unable to open /Users/tvleavitt/.local/share/flare/saves/empyrean/stash.txt! 2018-03-02 20:01:37.096

These go away after they're automatically created. Not critical, I presume. Most users will never notice, I'd guess.

dorkster commented 6 years ago

Hallelujah! Thank you for your hard work. I will gladly pull in your changes. We can ship the DMGs with your patch for now. We'll probably be doing a patch release later this month that addresses issues players found, and your patch can be rolled into that.

Those errors are fine and happen on every fresh game.

tvleavitt commented 6 years ago
  1. Still no icon? My wife has graphic design fu, we can create one if needed.
  2. Where do I put the created DMG files? They're 33 (flare-engine.dmg) and 168MB (flare.dmg) respectively.