From 3e90b1971a9f9890be584c47db12c2d922de5b37 Mon Sep 17 00:00:00 2001 From: Axel Kohlmeyer Date: Fri, 12 Mar 2021 22:21:11 -0500 Subject: [PATCH] add preliminary support for compiling/loading plugins on windows --- doc/src/plugin.rst | 3 ++ examples/plugins/CMakeLists.txt | 14 +++----- examples/plugins/Makefile.serial | 30 ++++++++++++++++ src/MAKE/Makefile.mpi | 2 +- src/MAKE/Makefile.serial | 2 +- src/plugin.cpp | 59 ++++++++++++++++++++++++-------- 6 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 examples/plugins/Makefile.serial diff --git a/doc/src/plugin.rst b/doc/src/plugin.rst index 25a55565b9..a75e39ccae 100644 --- a/doc/src/plugin.rst +++ b/doc/src/plugin.rst @@ -58,6 +58,9 @@ Restrictions Plugins are currently not available on Windows. +For the loading of plugins to work, the LAMMPS library must be +:ref:`compiled as a shared library `. + Plugins are dependent on the LAMMPS binary interface (ABI) and particularly the MPI library used. So they are not guaranteed to work when the plugin was compiled with a different MPI library diff --git a/examples/plugins/CMakeLists.txt b/examples/plugins/CMakeLists.txt index 74a1cd4e3b..2db2c041fd 100644 --- a/examples/plugins/CMakeLists.txt +++ b/examples/plugins/CMakeLists.txt @@ -31,11 +31,6 @@ endif() set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) -# bail out on windows -if(CMAKE_SYSTEM_NAME STREQUAL Windows) - message(FATAL_ERROR "LAMMPS plugins are currently not supported on Windows") -endif() - set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}) include(CheckIncludeFileCXX) include(LAMMPSInterfaceCXX) @@ -53,12 +48,13 @@ target_link_libraries(nve2plugin PRIVATE lammps) add_library(helloplugin MODULE helloplugin.cpp) target_link_libraries(helloplugin PRIVATE lammps) -set_target_properties(morse2plugin nve2plugin helloplugin PROPERTIES - PREFIX "" - LINK_FLAGS "-rdynamic") +set_target_properties(morse2plugin nve2plugin helloplugin PROPERTIES PREFIX "") -# MacOS seems to need this if(CMAKE_SYSTEM_NAME STREQUAL Darwin) set_target_properties(morse2plugin nve2plugin helloplugin PROPERTIES LINK_FLAGS "-Wl,-undefined,dynamic_lookup") +elseif(CMAKE_SYSTEM_NAME STREQUAL Windows) + set_target_properties(morse2plugin nve2plugin helloplugin PROPERTIES LINK_FLAGS "-Wl,--undefined") +else() + set_target_properties(morse2plugin nve2plugin helloplugin PROPERTIES LINK_FLAGS "-rdynamic") endif() diff --git a/examples/plugins/Makefile.serial b/examples/plugins/Makefile.serial new file mode 100644 index 0000000000..feb58bd9b3 --- /dev/null +++ b/examples/plugins/Makefile.serial @@ -0,0 +1,30 @@ +CXX=g++ +CXXFLAGS=-I../../src -I../../src/STUBS -Wall -Wextra -O3 -fPIC -I../../src/USER-OMP -fopenmp +LD=$(CXX) -shared -rdynamic -fopenmp + +default: morse2plugin.so nve2plugin.so helloplugin.so + +helloplugin.so: helloplugin.o + $(LD) -o $@ $^ + +morse2plugin.so: morse2plugin.o pair_morse2.o pair_morse2_omp.o + $(LD) -o $@ $^ + +nve2plugin.so: nve2plugin.o fix_nve2.o + $(LD) -o $@ $^ + +.cpp.o: + $(CXX) -o $@ $(CXXFLAGS) -c $< + +helloplugin.o: helloplugin.cpp + +pair_morse2.o: pair_morse2.cpp pair_morse2.h +pair_morse2_omp.o: pair_morse2_omp.cpp pair_morse2_omp.h pair_morse2.h +morse2plugin.o: morse2plugin.cpp pair_morse2.h pair_morse2_omp.h + +fix_nve2.o: fix_nve2.cpp fix_nve2.h +nve2plugin.o: nve2plugin.cpp fix_nve2.h + +clean: + rm -rf *~ *.so *.dylib *.o log.lammps CMakeCache.txt CMakeFiles + diff --git a/src/MAKE/Makefile.mpi b/src/MAKE/Makefile.mpi index c66e66c217..68e79e9e8e 100644 --- a/src/MAKE/Makefile.mpi +++ b/src/MAKE/Makefile.mpi @@ -18,7 +18,7 @@ SIZE = size ARCHIVE = ar ARFLAGS = -rc -SHLIBFLAGS = -shared +SHLIBFLAGS = -shared -rdynamic # --------------------------------------------------------------------- # LAMMPS-specific settings, all OPTIONAL diff --git a/src/MAKE/Makefile.serial b/src/MAKE/Makefile.serial index daf04cc5b0..8b4e2e5982 100644 --- a/src/MAKE/Makefile.serial +++ b/src/MAKE/Makefile.serial @@ -18,7 +18,7 @@ SIZE = size ARCHIVE = ar ARFLAGS = -rc -SHLIBFLAGS = -shared +SHLIBFLAGS = -shared -rdynamic # --------------------------------------------------------------------- # LAMMPS-specific settings, all OPTIONAL diff --git a/src/plugin.cpp b/src/plugin.cpp index f9bd36f875..2c4f2da396 100644 --- a/src/plugin.cpp +++ b/src/plugin.cpp @@ -24,12 +24,49 @@ #include #include -#ifdef _WIN32 +#if defined(_WIN32) #include #else #include #endif +#if defined(_WIN32) + +// open a shared object file +static void *my_dlopen(const char *fname) { + return (void *)LoadLibrary(fname); +} + +// resolve a symbol in shared object +static void *my_dlsym(void *h, const char *sym) { + return (void *)GetProcAddress((HINSTANCE)h, sym); +} + +// close a shared object +static int my_dlclose(void *h) { + /* FreeLibrary returns nonzero on success */ + return !FreeLibrary((HINSTANCE)h); +} + +#else + +// open a shared object file +static void *my_dlopen(const char *fname) { + return dlopen(fname, RTLD_NOW|RTLD_GLOBAL); +} + +// resolve a symbol in shared object +static void *my_dlsym(void *h, const char *sym) { + return dlsym(h, sym); +} + +// close a shared object +static int my_dlclose(void *h) { + return dlclose(h); +} + +#endif + namespace LAMMPS_NS { // list of plugin information data for loaded styles @@ -42,13 +79,11 @@ namespace LAMMPS_NS void plugin_load(const char *file, LAMMPS *lmp) { int me = lmp->comm->me; -#if defined(WIN32) - lmp->error->all(FLERR,"Loading of plugins on Windows not yet supported\n"); -#else // open DSO file from given path; load symbols globally - - void *dso = dlopen(file,RTLD_NOW|RTLD_GLOBAL); + + void *dso = my_dlopen(file); + if (dso == nullptr) { if (me == 0) utils::logmesg(lmp,fmt::format("Open of file {} failed\n",file)); @@ -58,9 +93,10 @@ namespace LAMMPS_NS // look up lammpsplugin_init() function in DSO // function must have C bindings so there is no name mangling - void *initfunc = dlsym(dso,"lammpsplugin_init"); + void *initfunc = my_dlsym(dso,"lammpsplugin_init"); + if (initfunc == nullptr) { - dlclose(dso); + my_dlclose(dso); if (me == 0) utils::logmesg(lmp,fmt::format("Plugin symbol lookup failure in " @@ -74,7 +110,6 @@ namespace LAMMPS_NS (*(lammpsplugin_initfunc)(initfunc))((void *)lmp, dso, (void *)&plugin_register); -#endif } /* -------------------------------------------------------------------- @@ -221,11 +256,7 @@ namespace LAMMPS_NS // if reference count is down to zero, close DSO handle. -- dso_refcounter[handle]; - if (dso_refcounter[handle] == 0) { -#ifndef WIN32 - dlclose(handle); -#endif - } + if (dso_refcounter[handle] == 0) my_dlclose(handle); } /* --------------------------------------------------------------------