1 #include <../../nrnconf.h>
14 #if NRNMPI_DYNAMICLOAD
20 #include "utils/logger.hpp"
26 extern void nrn_possible_mismatched_arch(
const char*);
29 #if DARWIN || defined(__linux__)
30 extern const char* path_prefix_to_libnrniv();
37 #include "nrnmpi_def_cinc"
39 #include "nrnmpi_dynam_cinc"
41 #include "nrnmpi_dynam_wrappers.inc"
42 #include "nrnmpi_dynam_stubs.cpp"
44 static void* load_mpi(
const char*
name, std::string& mes) {
50 nrn_possible_mismatched_arch(
name);
54 mes.append(
"successful");
60 static void* load_nrnmpi(
const char*
name, std::string& mes) {
62 mes.append(
"load_nrnmpi: ");
69 mes.append(
"successful\n");
70 for (
int i = 0; ftable[
i].name; ++
i) {
73 mes.append(
"load_nrnmpi: ");
74 mes.append(ftable[
i].
name);
84 auto*
const p =
reinterpret_cast<char* (**) (std::size_t)
>(
87 mes.append(
"load_nrnmpi: p_cxx_char_alloc ");
98 std::string nrnmpi_load() {
106 if (
info.dli_fname[0] ==
'/' || strchr(
info.dli_fname,
':')) {
107 pmes =
"<libmpi> is loaded in the sense the MPI_Initialized has an address\n";
124 using const_char_ptr =
const char*;
125 std::array libmpi_names {
127 "libmpi.dylib", const_char_ptr{std::getenv(
"MPI_LIB_NRN_PATH")},
135 "libmpi.so", const_char_ptr{std::getenv(
"MPI_LIB_NRN_PATH")},
"libmpich.so"
140 pmes =
"Tried loading an MPI library from:\n";
141 for (
auto const* mpi_path: libmpi_names) {
146 handle = load_mpi(mpi_path, pmes);
157 "Is an MPI library such as openmpi, mpich, intel-mpi or sgi-mpt installed? If yes, it "
158 "may be installed in a non-standard location that you can add to LD_LIBRARY_PATH (or "
159 "DYLD_LIBRARY_PATH on macOS), or on Linux or macOS you can provide a full path in "
160 "MPI_LIB_NRN_PATH\n");
164 #if !defined(DARWIN) && !defined(MINGW)
168 std::string
error{
"Promoted none of"};
169 auto const promote_to_global = [&
error](
const char* lib) {
172 error =
error +
' ' + lib +
" (" + (dlerr ? dlerr :
"nullptr") +
')';
177 if (!promote_to_global(
"libnrniv.so") && !promote_to_global(
"libnrniv-without-nvidia.so")) {
178 Fprintf(stderr, fmt::format(
"{} to RTLD_GLOBAL\n",
error).c_str());
186 auto const mpi_implementation = [
handle] {
193 }
else if (
dlsym(
handle,
"MPI_SGI_vtune_is_running")) {
212 auto const libnrnmpi_prefix = []() -> std::string {
217 if (
const char* nrn_home = std::getenv(
"NRNHOME")) {
219 return std::string{nrn_home} +
"/lib/";
222 return path_prefix_to_libnrniv();
228 auto const mpi_path = [&](std::string_view middle) {
229 std::string
name{libnrnmpi_prefix};
230 name.append(neuron::config::shared_library_prefix);
232 name.append(mpi_implementation);
233 name.append(neuron::config::shared_library_suffix);
236 auto const nrn_mpi_library = mpi_path(
"nrnmpi_");
243 #if defined(HAVE_SETENV)
247 if (!load_nrnmpi(nrn_mpi_library.c_str(), pmes)) {
260 void nrnmpi_load_or_exit() {
261 auto const err = nrnmpi_load();
263 Printf(fmt::format(
"{}\n", err).c_str());
DLFCN_EXPORT void * dlopen(const char *file, int mode)
DLFCN_EXPORT char * dlerror(void)
DLFCN_EXPORT int dlclose(void *handle)
DLFCN_EXPORT int dladdr(const void *addr, Dl_info *info)
DLFCN_NOINLINE DLFCN_EXPORT void * dlsym(void *handle, const char *name)
char * cxx_char_alloc(size_t sz)
handle_interface< non_owning_identifier< storage > > handle
Non-owning handle to a Mechanism instance.
std::string corenrn_mpi_library
int Fprintf(FILE *stream, const char *fmt, Args... args)
int Printf(const char *fmt, Args... args)