Relative Paths with Mac Application


Last week I released the first project developed with the TurtleBrains framework into the wild lands of the public. A few people even downloaded the Basic Pong game and let me know that worked on their system. The initial release on the Mac side was a little unfriendly to users, and I knew this was something the needed to improve upon before LudumDare 32, where TurtleBrains will get a real test.

I already knew that a Mac .app package was just a directory containing the executable and some other details, and spent two days attempting to package up the data folder and executable with no luck. I understood the issue, it was fairly simple, but had not a solution. When the executable started it would fail to load the sprite sheet and other data from a relative path. I copied the data folder everywhere, inside and outside of the package, and found no combination that worked.

After three days of attempting to solve the issue and talking with many others I had a partial solution, that I was not happy with, to call a function ToDataDirectory() which would do magic under the hood in TurtleBrains to give this. That is ugly though. Then someone mentioned to change working directory. Wow. I wrote up a small function to change the working directory under the situation that the working directory did not match the bundle path, these match when running from XCode, and the bundle path contains “.app”.  If both conditions are true set the working directory to the .app/Content/Resources/ directory, which is the location I will place the data.

Problem solved.

	char cwdBuffer[FILENAME_MAX];
	getcwd(cwdBuffer, FILENAME_MAX);

	const tbString currentDirectory(cwdBuffer);
	const tbString workingDirectory(ToString([[NSBundle mainBundle] bundlePath]));

	if (currentDirectory != workingDirectory && currentDirectory == tb_string("/")
	&& tbString::npos != workingDirectory.find(".app"))
		//workingDirectory is "/Some/Path/To/" running from application.
		//The packager script will put the data in ""
		chdir((workingDirectory + "/Contents/Resources/").c_str());

This code is executed during the launching of the GameApplication, hopefully before any assets have a chance to be loaded, and allows everything to work normally when running from a bundled .app package. I am happy with this solution, it is much cleaner than the alternative ToDataDirectory() and doesn’t require any release or deployment defines to be toggled.

Comments are closed.