Browse Source

Use -rpath=. for plugins. Set cwd when loading plugins.

tags/v2.0.0
Andrew Belt 4 years ago
parent
commit
5129c29a86
2 changed files with 47 additions and 32 deletions
  1. +5
    -5
      plugin.mk
  2. +42
    -27
      src/plugin.cpp

+ 5
- 5
plugin.mk View File

@@ -20,24 +20,24 @@ FLAGS += -I$(RACK_DIR)/include -I$(RACK_DIR)/dep/include
# I don't really understand the side effects (see GCC manual), but so far tests are positive. # I don't really understand the side effects (see GCC manual), but so far tests are positive.
FLAGS += -fno-gnu-unique FLAGS += -fno-gnu-unique


LDFLAGS += -shared
LDFLAGS += -Wl,-rpath=.
LDFLAGS += -L$(RACK_DIR) -lRack

include $(RACK_DIR)/arch.mk include $(RACK_DIR)/arch.mk


ifdef ARCH_LIN ifdef ARCH_LIN
LDFLAGS += -shared
TARGET := plugin.so TARGET := plugin.so
RACK_USER_DIR ?= $(HOME)/.Rack RACK_USER_DIR ?= $(HOME)/.Rack
# Link to glibc 2.23
# FLAGS += -include force_link_glibc_2.23.h
endif endif


ifdef ARCH_MAC ifdef ARCH_MAC
LDFLAGS += -shared -undefined dynamic_lookup
TARGET := plugin.dylib TARGET := plugin.dylib
LDFLAGS += -undefined dynamic_lookup
RACK_USER_DIR ?= $(HOME)/Documents/Rack RACK_USER_DIR ?= $(HOME)/Documents/Rack
endif endif


ifdef ARCH_WIN ifdef ARCH_WIN
LDFLAGS += -shared -L$(RACK_DIR) -lRack
TARGET := plugin.dll TARGET := plugin.dll
RACK_USER_DIR ?= "$(USERPROFILE)"/Documents/Rack RACK_USER_DIR ?= "$(USERPROFILE)"/Documents/Rack
endif endif


+ 42
- 27
src/plugin.cpp View File

@@ -43,51 +43,66 @@ namespace plugin {
// private API // private API
//////////////////// ////////////////////


static void* loadLibrary(std::string libraryPath) {
#if defined ARCH_WIN
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
std::wstring libraryFilenameW = string::toWstring(libraryPath);
HINSTANCE handle = LoadLibraryW(libraryFilenameW.c_str());
SetErrorMode(0);
if (!handle) {
int error = GetLastError();
throw Exception(string::f("Failed to load library %s: code %d", libraryPath.c_str(), error));
}
#else
// Plugin uses -rpath=. so change working directory so it can find libRack.
char cwd[PATH_MAX];
cwd[0] = '\0';
getcwd(cwd, sizeof(cwd));
chdir(asset::systemDir.c_str());
// And then change it back
DEFER({
chdir(cwd);
});
// Load library with dlopen
void* handle = dlopen(libraryPath.c_str(), RTLD_NOW | RTLD_LOCAL);
if (!handle) {
throw Exception(string::f("Failed to load library %s: %s", libraryPath.c_str(), dlerror()));
}
#endif
return handle;
}

typedef void (*InitCallback)(Plugin*); typedef void (*InitCallback)(Plugin*);


static InitCallback loadLibrary(Plugin* plugin) {
static InitCallback loadPluginCallback(Plugin* plugin) {
// Load plugin library // Load plugin library
std::string libraryFilename;
std::string libraryExt;
#if defined ARCH_LIN #if defined ARCH_LIN
libraryFilename = plugin->path + "/" + "plugin.so";
libraryExt = "so";
#elif defined ARCH_WIN #elif defined ARCH_WIN
libraryFilename = plugin->path + "/" + "plugin.dll";
libraryExt = "dll";
#elif ARCH_MAC #elif ARCH_MAC
libraryFilename = plugin->path + "/" + "plugin.dylib";
libraryExt = "dylib";
#endif #endif
std::string libraryPath = plugin->path + "/plugin." + libraryExt;


// Check file existence // Check file existence
if (!system::isFile(libraryFilename)) {
throw Exception(string::f("Library %s does not exist", libraryFilename.c_str()));
if (!system::isFile(libraryPath)) {
throw Exception(string::f("Library %s does not exist", libraryPath.c_str()));
} }


// Load dynamic/shared library // Load dynamic/shared library
#if defined ARCH_WIN
SetErrorMode(SEM_NOOPENFILEERRORBOX | SEM_FAILCRITICALERRORS);
std::wstring libraryFilenameW = string::toWstring(libraryFilename);
HINSTANCE handle = LoadLibraryW(libraryFilenameW.c_str());
SetErrorMode(0);
if (!handle) {
int error = GetLastError();
throw Exception(string::f("Failed to load library %s: code %d", libraryFilename.c_str(), error));
}
#else
void* handle = dlopen(libraryFilename.c_str(), RTLD_NOW | RTLD_LOCAL);
if (!handle) {
throw Exception(string::f("Failed to load library %s: %s", libraryFilename.c_str(), dlerror()));
}
#endif
plugin->handle = handle;
plugin->handle = loadLibrary(libraryPath);


// Get plugin's init() function // Get plugin's init() function
InitCallback initCallback; InitCallback initCallback;
#if defined ARCH_WIN #if defined ARCH_WIN
initCallback = (InitCallback) GetProcAddress(handle, "init");
initCallback = (InitCallback) GetProcAddress(plugin->handle, "init");
#else #else
initCallback = (InitCallback) dlsym(handle, "init");
initCallback = (InitCallback) dlsym(plugin->handle, "init");
#endif #endif
if (!initCallback) { if (!initCallback) {
throw Exception(string::f("Failed to read init() symbol in %s", libraryFilename.c_str()));
throw Exception(string::f("Failed to read init() symbol in %s", libraryPath.c_str()));
} }


return initCallback; return initCallback;
@@ -139,7 +154,7 @@ static Plugin* loadPlugin(std::string path) {
initCallback = core::init; initCallback = core::init;
} }
else { else {
initCallback = loadLibrary(plugin);
initCallback = loadPluginCallback(plugin);
} }
initCallback(plugin); initCallback(plugin);




Loading…
Cancel
Save