File paths appear to be resolved relative to source

May 11, 2020 at 3:37am
closed account (jECj6Up4)
I'm doing some asynchronous asset loading for a game, and I'm stumped by what seems completely weird to me. I have a root folder for the project with a makefile, a src/ directory for all the c/c++ source, and an asset/ directory for all the assets that are loaded this way. The executable is built to and run from this root directory. In my understanding, as long as I run from the root directory (where both the executable and "assets/" are), then it should be fine to load a file directly from assets (i.e. load_mesh("assets/obj/model.obj")), but it can't find the files this way. The only way I'm able to load these files are if I do load_mesh("../assets/obj/model.obj)", in other words, I can only load a file from a path relative to the SOURCE file where the loading code is, and not my current working directory. Any ideas?

May 11, 2020 at 5:06am
Yeah, the idea of "current" directory varies depending on how you run the program in the first place.

- Double clicking on the exe in your file explorer
- running from the command line
- Pressing 'run program' in your IDE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ cat foo.cpp
#include <iostream>
using namespace std;

int main(int argc, char *argv[])
{
  cout << argv[0] << endl;
 return 0;
}

$ ( cd cppForum/ ; ../a.out )
../a.out
$ ./a.out 
./a.out


https://linux.die.net/man/3/getcwd
https://linux.die.net/man/3/dirname

First check whether argv[0] is an absolute or relative path.

May 11, 2020 at 10:42am
closed account (jECj6Up4)
Sorry, I should have been clearer. I'm running from the command line, and argv[0] is a relative path.
May 11, 2020 at 12:55pm
So append the relative path of argv[0] onto the end of what getcwd() returns.
May 11, 2020 at 1:26pm
closed account (jECj6Up4)
getcwd() returns the expected directory, the root of the project, where the binary and /assets are.
May 11, 2020 at 2:13pm
Does load_mesh() do something with the path?
May 11, 2020 at 3:22pm
closed account (jECj6Up4)
I don't think so, but it does in turn call an asset import library which does the actual opening of the file. So I did a quick test, and did this in main:

1
2
3
4
FILE *fp = fopen("./assets/audio/sound.ogg", "r");
if (fp == NULL) {
    printf("failed to open file\n");
}


And this too fails, whereas FILE *fp = fopen("../assets/audio/sound.ogg", "r"); works just fine. I've ever seen this before!
May 11, 2020 at 4:39pm
> getcwd() returns the expected directory, the root of the project, where the binary and /assets are.
...
> And this too fails, whereas FILE *fp = fopen("../assets/audio/sound.ogg", "r"); works just fine.
One of these things doesn't make any sense.

You can't at the same time claim getcwd() is pointing to a directory containing "assets" and then go onto claim you need "../assets" in a relative path just to open a file.

May 11, 2020 at 4:46pm
closed account (jECj6Up4)
That's exactly what's so weird! The only way the loading works is if I use "../assets", and not "assets/". I'm really at a loss :P There must be something stupid I've overseen. I'll do some more debugging tomorrow and see.
Last edited on May 11, 2020 at 4:47pm
May 12, 2020 at 1:13am
You've gone full circle on this. Have you displayed your current directory? That's the only way you can tell if a relative directory makes sense.
May 12, 2020 at 5:05am
closed account (jECj6Up4)
Hehe, I'm really worried there must be some stupid oversight somewhere :) I'm on macOS catalina, and using fish shell, any chance that could be the source of any weirdness?
Last edited on May 12, 2020 at 5:13am
May 12, 2020 at 5:12am
closed account (jECj6Up4)
OK, confusion pt II: I know that getcwd returned the expected directory before, but when I run it now it returns the same directory PLUS "/resources". So the path issue makes sense now. But why does getcwd not report the directory I'm running the program from??

EDIT: In other words, getcwd != pwd

EDIT 2: OK, the reason why getcwd showed something different now than before is probably the order I ran things in. If getcwd is the first thing that happens, it shows the correct directory, and my simple file opening test works. BUT if I do it after creating my OpenGL context (using GLFW), it has changed to the /resources directory...
Last edited on May 12, 2020 at 5:16am
May 12, 2020 at 5:20am
closed account (jECj6Up4)
OK, it turns out it's a macos-specific caveat of "glfwInit()" that I had overlooked.

From their docs:

macOS: This function will change the current directory of the application to the Contents/Resources subdirectory of the application's bundle, if present. This can be disabled with the GLFW_COCOA_CHDIR_RESOURCES init hint.


Thanks for the help!
Topic archived. No new replies allowed.