@@ -19,22 +19,36 @@ limitations under the License.
19
19
#include < array>
20
20
#include < cstring>
21
21
#include < filesystem>
22
+ #include < system_error>
22
23
23
24
namespace P4 {
24
25
25
- #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__)
26
- #include < unistd.h>
27
-
28
26
#include < climits>
29
27
#ifdef __APPLE__
28
+ #include < unistd.h>
29
+
30
30
#include < mach-o/dyld.h>
31
- #endif
32
31
#elif defined(_WIN32)
33
32
#include < windows.h>
33
+ #else
34
+ #include < unistd.h>
34
35
#endif
35
36
36
37
std::filesystem::path getExecutablePath (const std::filesystem::path &suggestedPath) {
37
- #if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
38
+ #if defined(__APPLE__)
39
+ std::array<char , PATH_MAX> buffer{};
40
+ uint32_t size = static_cast <uint32_t >(buffer.size ());
41
+ if (_NSGetExecutablePath (buffer.data (), &size) == 0 ) {
42
+ return buffer.data ();
43
+ }
44
+ #elif defined(_WIN32)
45
+ std::array<char , PATH_MAX> buffer{};
46
+ // TODO: Do we need to support this?
47
+ DWORD size = GetModuleFileNameA (nullptr , buffer.data (), static_cast <DWORD>(buffer.size ()));
48
+ if (size > 0 && size < buffer.size ()) {
49
+ return buffer.data ();
50
+ }
51
+ #else
38
52
// Find the path of the executable. We use a number of techniques that may fail or work on
39
53
// different systems, and take the first working one we find. Fallback to not overriding the
40
54
// compiled-in installation path.
@@ -46,40 +60,20 @@ std::filesystem::path getExecutablePath(const std::filesystem::path &suggestedPa
46
60
};
47
61
48
62
for (const auto &path : paths) {
49
- try {
50
- // std::filesystem::canonical will throw on error if the path is invalid.
51
- // It will also try to resolve symlinks.
52
- return std::filesystem::canonical (path);
53
- } catch (const std::filesystem::filesystem_error &) {
54
- // Ignore and try the next path.
63
+ // std::filesystem::canonical will throw on error if the path is invalid.
64
+ // It will also try to resolve symlinks.
65
+ std::error_code errorCode;
66
+ auto canonicalPath = std::filesystem::canonical (path, errorCode);
67
+ // Return the path if no error was thrown.
68
+ if (!errorCode) {
69
+ return canonicalPath;
55
70
}
56
71
}
57
- #elif defined(__APPLE__)
58
- std::array<char , PATH_MAX> buffer{};
59
- uint32_t size = static_cast <uint32_t >(buffer.size ());
60
- if (_NSGetExecutablePath (buffer.data (), &size) == 0 ) {
61
- return buffer.data ();
62
- } else
63
- #elif defined(_WIN32)
64
- std::array<char , PATH_MAX> buffer{};
65
- // TODO: Do we need to support this?
66
- DWORD size = GetModuleFileNameA (nullptr , buffer.data (), static_cast <DWORD>(buffer.size ()));
67
- if (size > 0 && size < buffer.size ()) {
68
- return buffer.data ();
69
- } else
70
72
#endif
71
- if (auto *path = getenv (" _" )) {
72
- return path;
73
- }
74
73
// If the above fails, try to convert suggestedPath to a path.
75
- try {
76
- // std::filesystem::canonical will throw on error if the path is invalid.
77
- // It will also try to resolve symlinks.
78
- return std::filesystem::canonical (suggestedPath);
79
- } catch (const std::filesystem::filesystem_error &) {
80
- // In the case of an error, return an empty path.
81
- return {};
82
- }
74
+ std::error_code errorCode;
75
+ auto canonicalPath = std::filesystem::canonical (suggestedPath, errorCode);
76
+ return errorCode ? std::filesystem::path () : canonicalPath;
83
77
}
84
78
85
79
const char *exename (const char *argv0) {
0 commit comments