From 91fd728f3e0bd2b8bfd9669cca5710f1b81712bc Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sat, 29 May 2021 22:09:13 -0500 Subject: [PATCH] Add a default exec path logic. This adds default/fallback logic to determine the b2 exec absolute path as possible. It uses the arg0 and current dir or path to construct the liekliest path. fixes #25 --- doc/src/history.adoc | 5 +- src/engine/jam.cpp | 73 ---------------------------- src/engine/pathsys.cpp | 105 ++++++++++++++++++++++++++++++++++++++++- src/engine/pathsys.h | 8 ++++ 4 files changed, 116 insertions(+), 75 deletions(-) diff --git a/doc/src/history.adoc b/doc/src/history.adoc index 273c6f209..b5ae2a1df 100644 --- a/doc/src/history.adoc +++ b/doc/src/history.adoc @@ -31,10 +31,13 @@ -- _Peter Dimov_ * Add default value for cxx and cxxflags from env vars `CXX` and `CXXFLAGS` when using the custom `cxx` toolset to build the engine. - -- __Samuel Debionne_ and _René Ferdinand Rivera Morell_ + -- _Samuel Debionne_ and _René Ferdinand Rivera Morell_ * Fix detection of `intel-linux` toolset installation when only the compiler executable is in the `PATH`. -- _René Ferdinand Rivera Morell_ +* Fix `b2` executable path determination for platforms that don't have a + native method of getting the path to executables, like OpenBSD. + -- _René Ferdinand Rivera Morell_ == Version 4.5.0 diff --git a/src/engine/jam.cpp b/src/engine/jam.cpp index 9659bd1fd..a74786b46 100644 --- a/src/engine/jam.cpp +++ b/src/engine/jam.cpp @@ -707,76 +707,3 @@ int main( int argc, char * * argv ) return status ? EXITBAD : EXITOK; } - - -/* - * executable_path() - */ - -#if defined(_WIN32) -# define WIN32_LEAN_AND_MEAN -# include -char * executable_path( char const * argv0 ) -{ - char buf[ 1024 ]; - DWORD const ret = GetModuleFileNameA( NULL, buf, sizeof( buf ) ); - return ( !ret || ret == sizeof( buf ) ) ? NULL : strdup( buf ); -} -#elif defined(__APPLE__) /* Not tested */ -# include -char *executable_path( char const * argv0 ) -{ - char buf[ 1024 ]; - uint32_t size = sizeof( buf ); - return _NSGetExecutablePath( buf, &size ) ? NULL : strdup( buf ); -} -#elif defined(sun) || defined(__sun) /* Not tested */ -# include -char * executable_path( char const * argv0 ) -{ - const char * execname = getexecname(); - return execname ? strdup( execname ) : NULL; -} -#elif defined(__FreeBSD__) -# include -char * executable_path( char const * argv0 ) -{ - int mib[ 4 ] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - char buf[ 1024 ]; - size_t size = sizeof( buf ); - sysctl( mib, 4, buf, &size, NULL, 0 ); - return ( !size || size == sizeof( buf ) ) ? NULL : strndup( buf, size ); -} -#elif defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) -# include -char * executable_path( char const * argv0 ) -{ - char buf[ 1024 ]; - ssize_t const ret = readlink( "/proc/self/exe", buf, sizeof( buf ) ); - return ( !ret || ret == sizeof( buf ) ) ? NULL : strndup( buf, ret ); -} -#elif defined(OS_VMS) -# include -char * executable_path( char const * argv0 ) -{ - char * vms_path = NULL; - char * posix_path = NULL; - char * p; - - /* On VMS argv[0] shows absolute path to the image file. - * So, just remove VMS file version and translate path to POSIX-style. - */ - vms_path = strdup( argv0 ); - if ( vms_path && ( p = strchr( vms_path, ';') ) ) *p = '\0'; - posix_path = decc$translate_vms( vms_path ); - if ( vms_path ) free( vms_path ); - - return posix_path > 0 ? strdup( posix_path ) : NULL; -} -#else -char * executable_path( char const * argv0 ) -{ - /* If argv0 is an absolute path, assume it is the right absolute path. */ - return argv0[ 0 ] == '/' ? strdup( argv0 ) : NULL; -} -#endif diff --git a/src/engine/pathsys.cpp b/src/engine/pathsys.cpp index 9bbbcf875..4876534e7 100644 --- a/src/engine/pathsys.cpp +++ b/src/engine/pathsys.cpp @@ -28,9 +28,10 @@ */ #include "jam.h" -#include "pathsys.h" +#include "cwd.h" #include "filesys.h" +#include "pathsys.h" #include #include @@ -364,3 +365,105 @@ std::string b2::paths::normalize(const std::string &p) return result; } + + +/* + * executable_path() + */ + +#if defined(_WIN32) +# define WIN32_LEAN_AND_MEAN +# include +char * executable_path( char const * argv0 ) +{ + char buf[ 1024 ]; + DWORD const ret = GetModuleFileNameA( NULL, buf, sizeof( buf ) ); + return ( !ret || ret == sizeof( buf ) ) ? NULL : strdup( buf ); +} +#elif defined(__APPLE__) /* Not tested */ +# include +char *executable_path( char const * argv0 ) +{ + char buf[ 1024 ]; + uint32_t size = sizeof( buf ); + return _NSGetExecutablePath( buf, &size ) ? NULL : strdup( buf ); +} +#elif defined(sun) || defined(__sun) /* Not tested */ +# include +char * executable_path( char const * argv0 ) +{ + const char * execname = getexecname(); + return execname ? strdup( execname ) : NULL; +} +#elif defined(__FreeBSD__) +# include +char * executable_path( char const * argv0 ) +{ + int mib[ 4 ] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + char buf[ 1024 ]; + size_t size = sizeof( buf ); + sysctl( mib, 4, buf, &size, NULL, 0 ); + return ( !size || size == sizeof( buf ) ) ? NULL : strndup( buf, size ); +} +#elif defined(__linux__) || defined(__CYGWIN__) || defined(__GNU__) +# include +char * executable_path( char const * argv0 ) +{ + char buf[ 1024 ]; + ssize_t const ret = readlink( "/proc/self/exe", buf, sizeof( buf ) ); + return ( !ret || ret == sizeof( buf ) ) ? NULL : strndup( buf, ret ); +} +#elif defined(OS_VMS) +# include +char * executable_path( char const * argv0 ) +{ + char * vms_path = NULL; + char * posix_path = NULL; + char * p; + + /* On VMS argv[0] shows absolute path to the image file. + * So, just remove VMS file version and translate path to POSIX-style. + */ + vms_path = strdup( argv0 ); + if ( vms_path && ( p = strchr( vms_path, ';') ) ) *p = '\0'; + posix_path = decc$translate_vms( vms_path ); + if ( vms_path ) free( vms_path ); + + return posix_path > 0 ? strdup( posix_path ) : NULL; +} +#else +char * executable_path( char const * argv0 ) +{ + char * result = nullptr; + /* If argv0 is an absolute path, assume it is the right absolute path. */ + if (!result && b2::paths::is_rooted(argv0)) + result = strdup( argv0 ); + // If argv0 is a relative path, we can compute the absolute one from the + // current working dir. + if (!result && b2::paths::is_relative(argv0)) + { + auto p = b2::paths::normalize(b2::cwd_str()+"/"+argv0); + result = strdup( p.c_str() ); + } + // If it's a bare basename, search the PATH for a match. + if (!result) + { + std::string path_env = getenv( "PATH" ); + std::string::size_type i = 0; + while (i != std::string::npos) + { + std::string::size_type e = path_env.find_first_of(':', i); + std::string p = e == std::string::npos + ? path_env.substr(i) + : path_env.substr(i, e-i); + if (b2::filesys::is_file(p+"/"+argv0)) + { + result = strdup( (p+"/"+argv0).c_str() ); + break; + } + i = e == std::string::npos ? e : e+1; + } + } + return result; +} +#endif diff --git a/src/engine/pathsys.h b/src/engine/pathsys.h index 4aed9cf71..03ac403fa 100644 --- a/src/engine/pathsys.h +++ b/src/engine/pathsys.h @@ -108,6 +108,14 @@ namespace b2 (p.size() >= 1 && (p[0] == '/' || p[0] == '\\')); #endif } + inline bool is_relative(const std::string &p) + { + return + (p.size() >= 3 && ( + (p[0] == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\\')) || + (p[0] == '.' && (p[1] == '/' || p[1] == '\\')) + )); + } std::string normalize(const std::string &p); } }