Relative Paths Not Working in Xcode C++

23,792

Solution 1

Took me about 5 hours of Google and trying different things to FINALLY find the answer!

#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#endif

// ----------------------------------------------------------------------------
// This makes relative paths work in C++ in Xcode by changing directory to the Resources folder inside the .app bundle
#ifdef __APPLE__    
    CFBundleRef mainBundle = CFBundleGetMainBundle();
    CFURLRef resourcesURL = CFBundleCopyResourcesDirectoryURL(mainBundle);
    char path[PATH_MAX];
    if (!CFURLGetFileSystemRepresentation(resourcesURL, TRUE, (UInt8 *)path, PATH_MAX))
    {
        // error!
    }
    CFRelease(resourcesURL);

    chdir(path);
    std::cout << "Current Path: " << path << std::endl;
#endif
// ----------------------------------------------------------------------------

I've thrown some extra include guards because this makes it compile Apple only (I develop cross platform) and makes the code nicer.

I thank the other 2 guys for your answers, your help ultimately got me on the right track to find this answer so i've voted you both up. Thanks guys!!!!

Solution 2

Do not depend on the current working directory in binary code. Just don't. You cannot trust the operating system or shell to set it to where you expect it to be set, on Mac, Windows, or Unix.

For straight C, use _NSGetExecutablePath in dyld.h to get the path to your current executable, then you can go relative from there.

If you're just experimenting and want it to work, in Xcode choose Project > Edit Active Executable, and there's a panel there in which you can set the initial working directory to the project directory, the executable's parent directory, or any arbitrary directory. This should only be used for testing purposes. In the Mac OS, when you write a real app and launch it from the Finder, the working directory is /. And for Unix apps you have no control whatsoever over what the working directory is.

Solution 3

My guess is the type of app you're building is a one-off executable rather than being an executable app-bundle. On OS X and Unixes in general, resources are loaded from the absolute root of the drive which is different than Visual C++'s treatment of "root" being the path relative to project's root. Don't rely on the path ever being relative to anything in particular across OSes (or OS versions for that matter). You can set a working directory in Xcode but that will only impact applications launched from Xcode. If you were to execute it from the build directory in Finder, it'd once again be set to the root of the drive.

Share:
23,792
Brock Woolf
Author by

Brock Woolf

I predominantly code in Objective-C (Cocoa Touch) and C# (.net) I write games and utility software and do iPhone and iPad development. More here: BrockWoolf.com.

Updated on June 20, 2021

Comments

  • Brock Woolf
    Brock Woolf almost 3 years

    There are numerous post over the net that detail how relative paths don't work in Xcode. I do have an Xcode template that I downloaded where the relative paths DO work, however I have not been able to figure out why nor replicate it in other projects.

    Firstly, I am using C++ in Xcode 3.1. I am not using Objective-C, nor any Cocoa/Carbon frameworks, just pure C++.

    Here is the code that works in my other Xcode template:

    sound->LoadMusic( (std::string) "Resources/Audio/Pop.wav" );
    

    This relative path works for me also in Windows. Running the following command gives me an absolute path to the application's full path:

    std::cout << "Current directory is: " << getcwd( buffer, 1000) << "\n";
    

    /Applications/myApp

    How can we get relative paths to work in an Xcode .app bundle?