diff --git a/src/dlload.c b/src/dlload.c index 71af6238b4cf6..7106ab0e9ba17 100644 --- a/src/dlload.c +++ b/src/dlload.c @@ -163,6 +163,7 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, uv_stat_t stbuf; void *handle; int abspath; + int is_atpath; // number of extensions to try — if modname already ends with the // standard extension, then we don't try adding additional extensions int n_extensions = endswith_extension(modname) ? 1 : N_EXTENSIONS; @@ -188,16 +189,30 @@ JL_DLLEXPORT void *jl_load_dynamic_library(const char *modname, unsigned flags, } abspath = isabspath(modname); + is_atpath = 0; + + // Detect if our `modname` is something like `@rpath/libfoo.dylib` +#ifdef _OS_DARWIN_ + size_t nameLen = strlen(modname); + const char *const atPaths[] = {"@executable_path/", "@loader_path/", "@rpath/"}; + for (i = 0; i < sizeof(atPaths)/sizeof(char*); ++i) { + size_t atLen = strlen(atPaths[i]); + if (nameLen >= atLen && 0 == strncmp(modname, atPaths[i], atLen)) { + is_atpath = 1; + } + } +#endif /* this branch permutes all base paths in DL_LOAD_PATH with all extensions note: skip when !jl_base_module to avoid UndefVarError(:DL_LOAD_PATH), and also skip for absolute paths + and also skip for `@`-paths on macOS We also do simple string replacement here for elements starting with `@executable_path/`. While these exist as OS concepts on Darwin, we want to use them on other platforms such as Windows, so we emulate them here. */ - if (!abspath && jl_base_module != NULL) { + if (!abspath && !is_atpath && jl_base_module != NULL) { jl_binding_t *b = jl_get_module_binding(jl_base_module, jl_symbol("DL_LOAD_PATH")); jl_array_t *DL_LOAD_PATH = (jl_array_t*)(b ? b->value : NULL); if (DL_LOAD_PATH != NULL) {