1

I have a specific problem with compiling my program on a Mac. At this point everything is good with on a Windows. So I'm sure that the problem is not inside the code, it is a platform problem only.

What I use:

My current project is a very small game I used to start to study C++ so I used several textures to load them to create sprites and backgrounds.

#include <map>
#include <string>

std::map<std::string, const char *> assetsPaths{{"worldMap", "../assets/worldMap.png"},
                                                {"knightIdle", "../assets/character/knight_idle_spritesheet.png"},
                                                {"knightRun", "../assets/character/knight_run_spritesheet.png"},
                                                {"goblinIdle", "../assets/enemy/goblin/goblin_idle_spritesheet.png"},
                                                {"goblinRun", "../assets/enemy/goblin/goblin_run_spritesheet.png"},
                                                {"rock", "../assets/obstacles/rock.png"},
                                                {"log", "../assets/obstacles/log.png"},
                                                {"sword", "../assets/weapon/sword/weapon_sword.png"}};

You may notice that all paths are relative to executable position.

Then when I start the game from the IDE everything seems to work fine:

INFO: FILEIO: [../assets/enemy/goblin/goblin_idle_spritesheet.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 3] Texture loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/enemy/goblin/goblin_run_spritesheet.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 4] Texture loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/character/knight_idle_spritesheet.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 5] Texture loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/character/knight_run_spritesheet.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 6] Texture loaded successfully (96x16 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/obstacles/log.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (27x16 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 7] Texture loaded successfully (27x16 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/obstacles/rock.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (22x21 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 8] Texture loaded successfully (22x21 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/weapon/sword/weapon_sword.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (16x16 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 9] Texture loaded successfully (16x16 | R8G8B8A8 | 1 mipmaps)
INFO: FILEIO: [../assets/worldMap.png] File loaded successfully
INFO: IMAGE: Data loaded successfully (768x768 | R8G8B8A8 | 1 mipmaps)
INFO: TEXTURE: [ID 10] Texture loaded successfully (768x768 | R8G8B8A8 | 1 mipmaps)

game with textures loaded

But when I'm trying to run executable in a folder I'm getting this:

WARNING: FILEIO: [../assets/enemy/goblin/goblin_idle_spritesheet.png] Failed to open file
WARNING: FILEIO: [../assets/enemy/goblin/goblin_run_spritesheet.png] Failed to open file
WARNING: FILEIO: [../assets/character/knight_idle_spritesheet.png] Failed to open file
WARNING: FILEIO: [../assets/character/knight_run_spritesheet.png] Failed to open file
WARNING: FILEIO: [../assets/obstacles/log.png] Failed to open file
WARNING: FILEIO: [../assets/obstacles/rock.png] Failed to open file
WARNING: FILEIO: [../assets/weapon/sword/weapon_sword.png] Failed to open file
WARNING: FILEIO: [../assets/worldMap.png] Failed to open file

game without textures

I understood that the problem is somewhere in reading paths. So when I tried to use absolute paths just to test my theory everything worked fine. But it is very inconvenient because game definitely will not work on another machine.

I tried this line of code to understand what is happening.

std::cout << "Run path: " << GetWorkingDirectory() << std::endl;

And there are results:

Running via IDE:

Run path: /Users/nickrimer/cpp/classy_clash_game/cmake-build-debug

Running via executable in a folder:

Run path: /Users/nickrimer

I don't know why but system thinks that I'm running inside of my root folder, of course there are no assets on this path. I make sure that file I'm running lies inside this folder: /Users/nickrimer/cpp/classy_clash_game/cmake-build-debug

Actually it doesn't even matter in which folder this executable will be placed, its executable context is always incorrect and always refers to a root folder.

So the question is how to run executable on a MacOS platform with the right execution context?

Please just tell me if I have to provide you more necessary information about this build.

user438383
  • 5,716
  • 8
  • 28
  • 43
Nick_Rimer
  • 191
  • 1
  • 9
  • 2
    If you run the program in certain ways you'll have the exact same problem on Windows. The solution is to first figure out the path to your executable (there are various platform specific APIs for that - on Linux you'd read the `/proc/self/exe` symlink for example, on MacOS an Windows there are other ways), then load your resources relative to your executables path. – Jesper Juhl Nov 07 '22 at 17:43
  • 1
    [Get path of executable](https://stackoverflow.com/questions/1528298/get-path-of-executable) should help. You need to find where your executable is and set the working directory so that the relative paths work. – Retired Ninja Nov 07 '22 at 17:45
  • An alternative way to fix the problem would be to bake the resources right into your executable and then load/access them from memory at runtime, rather than having them as separate files on disk. – Jesper Juhl Nov 07 '22 at 17:48
  • Also, remember, that at runtime, your current working directory (`cwd`) (which is what relative paths are resolved against) is *not* always the same as your executables directory (depending on how the application is launched) - unless you explicitly change it to be so. – Jesper Juhl Nov 07 '22 at 17:53
  • There is no such problem on Windows platform with the same code. Executable works well and loads assets from where it should. But as we can see executable on MacOS thinks that it was started from another folder (root). I guarantee that all assets are on their places. – Nick_Rimer Nov 07 '22 at 17:55
  • @Nick_Rimer There *is* the same problem on Windows. Try this: Start a `cmd` shell. Make and change to a random directory of the `C:` drive (`mkdir C:\foo` then `cd C:\foo`). Run your program as `C:\path\to\your\thing.exe` - it won't be able to find its resources since `cwd` is "C:\foo" and *not* " C:\path\to\your\" , so the relative paths will be wrong. – Jesper Juhl Nov 07 '22 at 18:00
  • @Nick_Rimer If you double click, sure the exe will be launched with the directory containing the exe as working directory. Create a shortcut and edit the properties so that the directory the program is executed in differs from the directory containing the executable and you should see the same issues. – fabian Nov 07 '22 at 19:03

1 Answers1

0

I don't know how this wasn't suggested before, but Raylib provides a solution for this:

// Get the directory of the running application (uses static string)
const char *GetApplicationDirectory(void);

Furthermore, Raylib also provides a function to get and change the current directory, so something like this should work to loading your assets:

prev_dir = GetWorkingDirectory();
app_dir  = GetApplicationDirectory();

ChangeDirectory(app_dir);
// load your assets
ChangeDirectory(prev_dir);