Victor's Weblog

Hi! I'm Victor Vasiliev. I study math and computer science at MIT, and spend my spare time writing open source software and playing video games. I also used to be active as MediaWiki developer.

GitHub: vasilvv
Twitter: @vasilvv_
Email: vasilvv@mit.edu

Atom feed · Archive

Where am I? Locating yourself on different platforms

It happens every so often that a program needs to figure out where its executable file is located. A common situation is when you are writing a unit test, and your test data is located in the same directory as your binary.

Unfortunately, POSIX does not provide any interface to do that, so if you are writing portable C/C++ code, you are in for an adventure. Below are short code snippets which do that on various platforms. Try to guess which ones work with which platform.

Disclaimer: those are the snippets which I have collected from various API references, StackOverflow answers and SDL source code. I have not tested them, and you should not assume they actually always work correctly.

Variant 1

GetModuleFileName(NULL, path, sizeof(path));

Variant 2

path = getexecname();

Variant 3

/* This is, of course, an oversimplification.  In practice, you would want to
 * do the link expansion recursively, or at least one level more deep than
 * this. */
readlink("/proc/self/exe", path, sizeof(path))

Variant 4(a)

readlink("/proc/curproc/file", path, sizeof(path))

Variant 4(b), from the same platform as above

const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
sysctl(mib, sizeof(mib), path, sizeof(path), NULL, 0);

Variant 5

_NSGetExecutablePath(path, &path_size);

As a bonus, here is the same problem solved in higher-level languages.

Variant 6 (used in multiple languages)

__FILE__

Variant 7 (strictly speaking, returns the directory instead of the file)

AppDomain.CurrentDomain.BaseDirectory

Variant 8

SomeClass.class.getProtectionDomain().getCodeSource().getLocation().getPath();

The answers here are (highlight to show): #1 is Windows, #2 is Solaris, #3 is Linux, #4 is FreeBSD, #5 is OS X, #6 could be Python, Perl, PHP, Ruby (and probably others as well), #7 is C# and #8 is Java.

In practice, many frameworks (like SDL or Qt) have already solved that problem once, and you can just call SDL_GetBasePath or QCoreApplication::applicationFilePath() to get the path you need.