1515#if TCL_MAJOR_VERSION >= 9 && !defined(USE_TCL_RUNFILE_INIT)
1616#include " bazel/tcl_resources_zip_data.h"
1717#else
18- # ifdef __linux__
19- #include < linux/ limits.h>
18+
19+ #include < limits.h>
2020#include < unistd.h>
21+
22+ #if defined(__APPLE__)
23+ #include < mach-o/dyld.h>
24+ #include < sys/param.h>
2125#endif
2226
2327#include < memory>
2630#endif
2731
2832namespace in_bazel {
33+
34+ // Avoid adding any dependencies like boost.filesystem
35+ // Returns path to running binary if possible.
36+ static std::string GetProgramLocation ()
37+ {
38+ #if defined(_WIN32)
39+ char result[MAX_PATH + 1 ] = {' \0 ' };
40+ auto path_len = GetModuleFileNameA (NULL , result, MAX_PATH );
41+ #elif defined(__APPLE__)
42+ char result[MAXPATHLEN + 1 ] = {' \0 ' };
43+ uint32_t path_len = MAXPATHLEN ;
44+ if (_NSGetExecutablePath (result, &path_len) != 0 ) {
45+ path_len = readlink (result, result, MAXPATHLEN );
46+ }
47+ #else
48+ char result[PATH_MAX + 1 ] = {' \0 ' };
49+ ssize_t path_len = readlink (" /proc/self/exe" , result, PATH_MAX );
50+ #endif
51+ if (path_len > 0 ) {
52+ return result;
53+ }
54+ return Tcl_GetNameOfExecutable ();
55+ }
56+
2957static std::optional<std::string> TclLibraryMountPoint (Tcl_Interp* interp)
3058{
3159 // In tcl9, we can use //zipfs:/ otherwise we need to point to the
@@ -41,26 +69,8 @@ static std::optional<std::string> TclLibraryMountPoint(Tcl_Interp* interp)
4169#else
4270 using rules_cc::cc::runfiles::Runfiles;
4371 std::string error;
44- // Use /proc/self/exe to resolve the real binary path, as argv[0] may
45- // point into a sandbox where the .runfiles tree does not exist.
46- std::string exe_path;
47- #ifdef __linux__
48- char buf[PATH_MAX + 1 ];
49- ssize_t len = readlink (" /proc/self/exe" , buf, PATH_MAX );
50- if (len > 0 && len < PATH_MAX ) {
51- exe_path.assign (buf, len);
52- } else {
53- if (len >= PATH_MAX ) {
54- std::cerr << " [Error] /proc/self/exe path too long (>= PATH_MAX); "
55- " falling back to Tcl_GetNameOfExecutable()\n " ;
56- }
57- exe_path = Tcl_GetNameOfExecutable ();
58- }
59- #else
60- exe_path = Tcl_GetNameOfExecutable ();
61- #endif
6272 std::unique_ptr<Runfiles> runfiles (
63- Runfiles::Create (exe_path , BAZEL_CURRENT_REPOSITORY , &error));
73+ Runfiles::Create (GetProgramLocation () , BAZEL_CURRENT_REPOSITORY , &error));
6474 if (!runfiles) {
6575 std::cerr << " [Warning] Failed to create bazel runfiles: " << error << " \n " ;
6676 return std::nullopt ;
0 commit comments