Skip to content

Instantly share code, notes, and snippets.

@drdanz
Last active March 27, 2019 13:59
Show Gist options
  • Save drdanz/d5fb1d85ffdb9122692c36715e2b3e53 to your computer and use it in GitHub Desktop.
Save drdanz/d5fb1d85ffdb9122692c36715e2b3e53 to your computer and use it in GitHub Desktop.
getLibraryPath, getCurrentExecutablePath, and getInstallPrefix
#include "bar.h"
void bar::dummy() {}
#ifndef BAR_H
#define BAR_H
namespace bar {
void dummy();
}
#endif // BAR_H
cmake_minimum_required(VERSION 3.0)
project(foo)
find_package(YARP REQUIRED)
add_library(foo SHARED foo.cpp foo.h)
target_link_libraries(foo PRIVATE dl)
add_library(bar STATIC bar.cpp bar.h)
add_executable(main main.cpp)
target_link_libraries(main PRIVATE YARP::YARP_OS
YARP::YARP_init
foo
bar)
#include "foo.h"
#include <string>
#if defined(__linux__)
# include <link.h>
# include <unistd.h>
# include <limits.h>
#elif defined (__APPLE__)
# include <mach-o/dyld.h>
#endif
namespace {
// FIXME Replace with string_view.size()
static size_t constexpr strlength(const char* str)
{
return *str ? 1 + strlength(str + 1) : 0;
}
}
// Linux: http://stackoverflow.com/a/27522149
// macOS: http://stackoverflow.com/a/30293362
// Windows: http://stackoverflow.com/a/6706716
std::string yarp::os::getLibraryPath(const std::string& libname)
{
std::string library_path;
#if defined(__linux__) // MINGW? CYGWIN?
link_map* map = reinterpret_cast<link_map*>(dlopen(NULL, RTLD_NOW));
if (map && map->l_next) {
map = map->l_next->l_next;;
}
while (map) {
std::string name = map->l_name;
size_t pos = name.find("/lib" + libname + ".");
if (pos != std::string::npos) {
library_path = name.substr(0, pos);
break;
}
map = map->l_next;
}
#elif defined(__APPLE__)
for (uint32_t count = 0; count < _dyld_image_count(); ++count) {
std::string name = _dyld_get_image_name(count);
size_t pos = name.find("/lib" + libname + ".");
if (pos != std::string::npos) {
library_path = name.substr(0, pos);
break;
}
}
#elif defined(WIN32) // MSVC? MINGW? CYGWIN?
// FIXME should check for "YARP_OSd.dll" as well
HMODULE hModule = GetModuleHandle(_T(libname + ".dll"));
TCHAR dllPath[_MAX_PATH];
GetModuleFileName(hModule, dllPath, _MAX_PATH);
library_path = dllPath;
#else
// path.d not supported
#endif
return library_path;
}
std::string yarp::os::getCurrentExecutablePath()
{
std::string current_executable_path;
// FIXME
#if defined(__linux__) // MINGW? CYGWIN?
char buf[PATH_MAX + 1];
if (readlink("/proc/self/exe", buf, sizeof(buf) - 1) != -1) {
current_executable_path = buf;
current_executable_path = current_executable_path.substr(0, current_executable_path.rfind('/'));
}
#elif defined(__APPLE__)
// _NSGetExecutablePath
#elif defined(WIN32)
// GetModuleFileName / GetModuleFileNameA
#endif
return current_executable_path;
}
std::string yarp::os::getInstallPrefix()
{
#if defined(_MSC_VER) && !defined(NDEBUG)
std::string install_prefix = yarp::os::getLibraryPath("YARP_OSd");
#else
std::string install_prefix = yarp::os::getLibraryPath("YARP_OS");
#endif
if(install_prefix.empty()) {
// YARP is compiled statically
install_prefix = yarp::os::getCurrentExecutablePath();
} else {
static constexpr size_t lib_dir_size = strlength(CMAKE_LIBRARY_DIR);
if (install_prefix.substr(install_prefix.size() - lib_dir_size) == CMAKE_LIBRARY_DIR) {
install_prefix = install_prefix.substr(0, install_prefix.size() - (lib_dir_size + 1));
}
}
return install_prefix;
}
#ifndef FOO_H
#define FOO_H
// FIXME
#define YARP_OS_API
#define CMAKE_LIBRARY_DIR "lib"
#include <string>
namespace yarp {
namespace os {
/**
* @brief Get the install prefix for the library @c libname
*
* @param libname The name of the library, without prefix and extension
*/
YARP_OS_API std::string getLibraryPath(const std::string& libname);
YARP_OS_API std::string getCurrentExecutablePath();
/**
* @brief Get YARP install prefix
*/
YARP_OS_API std::string getInstallPrefix();
}
}
#endif // FOO_H
#include "foo.h"
#include "bar.h"
#include <yarp/os/Network.h>
#include <iostream>
int main(int argc, char *argv[])
{
bar::dummy();
yarp::os::Network yarp;
std::cout << "YARP install prefix: " << yarp::os::getInstallPrefix() << '\n';
std::cout << "foo (shared): " << yarp::os::getLibraryPath("foo") << '\n';
std::cout << "bar (static): " << yarp::os::getLibraryPath("bar") << '\n';
std::cout << "baz (missing): " << yarp::os::getLibraryPath("baz") << '\n';
std::cout << "current executable path: " << yarp::os::getCurrentExecutablePath() << '\n';
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment