Skip to content

Commit

Permalink
setting up a way for calling pycv wit the python module
Browse files Browse the repository at this point in the history
Now pycv works with pip

Reordering the installation procedure

added a sort of "FIND PLUMED" that does not work

setting up a second run option, adding an helper

removed the self-import gor getting the path of pycv

adding an example

Better CMakefiles

now it shoudl work with plumed from pkg-config or not installed (just needs the plumed executable in the path)

Restored the Makefile

restoring the standalone tests

adding some extra tests

updating the WF

Now pycv appears to load correcly

set up aslo a few basic tests for pyfunc

updated the docker recipes with the new installation method of pycv

using pip3 in the makefile

sourcing the correct bashrc in rocky8

Now the tests are compatible with  with GNUsed and BSDsed
  • Loading branch information
Iximiel committed Jan 23, 2025
1 parent df781b4 commit 2d68d11
Show file tree
Hide file tree
Showing 105 changed files with 1,944 additions and 229 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/linuxWF.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,7 @@ jobs:
if: contains( matrix.variant, '-pycv-' )
working-directory: ./plugins/pycv/
run: |
pip install --user -r requirements.txt
source ../../sourceme.sh
ln -s $(realpath ../../regtest/scripts) ./regtest/scripts
./prepareMakeForDevelop.sh
make check
13 changes: 11 additions & 2 deletions docker/fedora39-pycv
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@ FROM plumed:fedora39

RUN source /etc/bashrc \
&& module load mpi \
&& export OMPI_MCA_btl_base_warn_component_unused=0 \
&& export OMPI_MCA_btl_base_verbose=0 \
&& export OMPI_MCA_plm=isolated \
&& export OMPI_MCA_btl_vader_single_copy_mechanism=none \
&& export OMPI_MCA_rmaps_base_oversubscribe=yes \
&& export PATH=$HOME/opt/bin:$PATH \
&& export CPATH=$HOME/opt/include:$CPATH \
&& export INCLUDE=$HOME/opt/include:$INCLUDE \
&& export LIBRARY_PATH=$HOME/opt/lib:$LIBRARY_PATH \
&& export LD_LIBRARY_PATH=$HOME/opt/lib:$LD_LIBRARY_PATH \
&& cd plumed2 \
&& source ./sourceme.sh \
&& cd plugins/pycv \
&& pip3 install -r requirements.txt \
&& ./configurePyCV.sh \
&& ln -s $(realpath ../../regtest/scripts) ./regtest/scripts \
&& python_bin=python3 ./prepareMakeForDevelop.sh \
&& make check
15 changes: 12 additions & 3 deletions docker/rocky8-pycv
Original file line number Diff line number Diff line change
@@ -1,11 +1,20 @@
FROM plumed:rocky8

RUN source ./.bashrc \
RUN . ./.bashrc \
&& module load mpi \
&& export OMPI_MCA_btl_base_warn_component_unused=0 \
&& export OMPI_MCA_btl_base_verbose=0 \
&& export OMPI_MCA_plm=isolated \
&& export OMPI_MCA_btl_vader_single_copy_mechanism=none \
&& export OMPI_MCA_rmaps_base_oversubscribe=yes \
&& export PATH=$HOME/opt/bin:$PATH \
&& export CPATH=$HOME/opt/include:$CPATH \
&& export INCLUDE=$HOME/opt/include:$INCLUDE \
&& export LIBRARY_PATH=$HOME/opt/lib:$LIBRARY_PATH \
&& export LD_LIBRARY_PATH=$HOME/opt/lib:$LD_LIBRARY_PATH \
&& cd plumed2 \
&& source ./sourceme.sh \
&& cd plugins/pycv \
&& pip3 install --user -r requirements.txt \
&& ./configurePyCV.sh \
&& ln -s $(realpath ../../regtest/scripts) ./regtest/scripts \
&& python_bin=python3 ./prepareMakeForDevelop.sh \
&& make check
5 changes: 4 additions & 1 deletion plugins/pycv/.gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
/Makefile.conf
*.o
*.so
env
/env*/
/build*/
/dist*/
*.whl
75 changes: 75 additions & 0 deletions plugins/pycv/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
cmake_minimum_required(VERSION 3.15...3.27)
project(
${SKBUILD_PROJECT_NAME}
VERSION ${SKBUILD_PROJECT_VERSION}
LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)

message(
STATUS
"Everithing should work fine if you are in the same environment in which you have compiled plumed"
)
# FinPlumed is here:
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
# Finding necessary packages
find_package(Python REQUIRED COMPONENTS Interpreter Development)
find_package(pybind11 CONFIG REQUIRED)
find_package(Plumed REQUIRED)

# Finding optionals things
if(Plumed_HAS_MPI)
find_package(MPI REQUIRED)
endif()
if(MPI_CXX_FOUND)
list(APPEND extraLibs MPI::MPI_CXX)
endif()

if(Plumed_HAS_OPENMP)
find_package(OpenMP REQUIRED)
endif()
if(OpenMP_CXX_FOUND)
list(APPEND extraLibs OpenMP::OpenMP_CXX)
endif()

include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fno-gnu-unique USE_NO_GNU_UNIQUE)
if(USE_NO_GNU_UNIQUE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-gnu-unique")
endif()

# plumed_STATIC_LDFLAGS_OTHER:INTERNAL=-rdynamic;-Wl,-Bsymbolic;-fopenmp
# -rdynamic is automatically set by cmake, and also -fPIC

################################################################################
################################the pycv library################################
################################################################################

add_library(
PythonCVInterface SHARED src/ActionWithPython.cpp src/PythonCVInterface.cpp
src/PythonFunction.cpp)
# public, so they trickle down to the python module
target_compile_definitions(PythonCVInterface PUBLIC ${Plumed_CFLAGS})
target_include_directories(PythonCVInterface PUBLIC src ${Plumed_INCLUDEDIR})
# ####################################################################
# uncommenting this brings problems since some symbols here are needed
# by the python module even if it should be the correct setting...
# https://gcc.gnu.org/wiki/Visibility could be a starting point
#######################################################################
# target_compile_options(PythonCVInterface PRIVATE -fvisibility=hidden)
target_link_libraries(PythonCVInterface PRIVATE pybind11::embed)
target_link_libraries(PythonCVInterface PUBLIC plumedKernel ${extraLibs})
# this removes the "lib" prefix
set_target_properties(PythonCVInterface PROPERTIES PREFIX "")

install(TARGETS PythonCVInterface DESTINATION pycv)

################################################################################
###########################The pvCV companion module############################
################################################################################

pybind11_add_module(plumedCommunications src/PlumedPythonEmbeddedModule.cpp)
target_link_libraries(plumedCommunications PRIVATE pybind11::headers)
target_link_libraries(plumedCommunications PUBLIC PythonCVInterface)

# The install directory is the output (wheel) directory
install(TARGETS plumedCommunications DESTINATION .)
87 changes: 87 additions & 0 deletions plugins/pycv/FindPlumed.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
if(NOT Plumed_FOUND)
find_package(PkgConfig)
if(Plumed_FIND_QUIETLY)
function(message)
# THIS completely shuts down messages
endfunction()
pkg_check_modules(PLUMED QUIET plumedInternals)
else()
pkg_check_modules(PLUMED plumedInternals)
endif()

if(Plumed_FOUND)
if("-D__PLUMED_HAS_MPI=1" IN_LIST Plumed_CFLAGS)
set(Plumed_HAS_MPI
1
CACHE INTERNAL "plumed has MPI")
endif()
if("-fopenmp" IN_LIST Plumed_STATIC_LDFLAGS_OTHER)
set(Plumed_HAS_OPENMP
1
CACHE INTERNAL "plumed has OpenMP")
endif()
else()
message(STATUS "plumed not found via pkgconfig, trying executable")

execute_process(
COMMAND plumed --no-mpi info --include-dir
RESULT_VARIABLE PLUMED_EXECUTABLE
OUTPUT_QUIET ERROR_QUIET)
if(PLUMED_EXECUTABLE EQUAL 0)
set(Plumed_FOUND
1
CACHE INTERNAL "plumed found")

message(STATUS "Configuring plumed from executable")
execute_process(
COMMAND plumed --no-mpi info --include-dir
OUTPUT_VARIABLE Plumed_INCLUDEDIR
OUTPUT_STRIP_TRAILING_WHITESPACE)

set(Plumed_INCLUDEDIR
${Plumed_INCLUDEDIR}
CACHE INTERNAL "plumed include dir")
execute_process(
COMMAND plumed --no-mpi info --configuration
OUTPUT_VARIABLE Plumed_CONFIG
OUTPUT_STRIP_TRAILING_WHITESPACE)

set(Plumed_CPP_FLAGS "")

string(REPLACE "\n" ";" ProcessFile_LINES "${Plumed_CONFIG}")
foreach(_line ${ProcessFile_LINES})
if(${_line} MATCHES "CPPFLAGS=.*")
set(Plumed_CPP_FLAGS ${_line})
string(REGEX REPLACE "CPPFLAGS= *" "" Plumed_CPP_FLAGS
${Plumed_CPP_FLAGS})
string(REPLACE "\\" "" Plumed_CPP_FLAGS ${Plumed_CPP_FLAGS})
string(REPLACE "-D" ";" Plumed_CPP_FLAGS ${Plumed_CPP_FLAGS})
# message(STATUS "Found PLUMED CPP_FLAGS: \"${Plumed_CPP_FLAGS}\"")
# message(STATUS "Found PLUMED CPP_FLAGS:") foreach(_flag
# ${Plumed_CPP_FLAGS}) message(STATUS " \"${_flag}\"") endforeach()
endif()
if(${_line} MATCHES ".*-fopenmp.*")
set(Plumed_HAS_MPI
1
CACHE INTERNAL "plumed has MPI")
endif()
endforeach()
set(Plumed_CFLAGS
${Plumed_CPP_FLAGS}
CACHE INTERNAL "plumed Definitions flags")

execute_process(COMMAND plumed --no-mpi config -q has mpi
RESULT_VARIABLE Plumed_WITH_MPI)
if(Plumed_WITH_MPI EQUAL 0)
set(Plumed_HAS_MPI
1
CACHE INTERNAL "plumed has MPI")
endif()

else()
if(Plumed_FIND_REQUIRED)
message(FATAL_ERROR "plumed not found")
endif()
endif()
endif()
endif()
65 changes: 20 additions & 45 deletions plugins/pycv/Makefile
Original file line number Diff line number Diff line change
@@ -1,53 +1,28 @@
# include the machine dependent configuration
ifneq ($(MAKECMDGOALS),clean)
-include ../../Makefile.conf
ifndef canPyCV
include ./Makefile.conf
endif
endif

.PHONY: clean check all
#Dependency tracking based on https://make.mad-scientist.net/papers/advanced-auto-dependency-generation/#tldr
#this assumes gcc
DEPDIR := .deps
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
PYBIND11FLAG =
ADDCPPFLAGS:=$(python_cf_embedded) $(pybind11_cflags) $(ADDCPPFLAGS)
ADDCLDFLAGS:=$(ADDCLDFLAGS) $(python_ld_embedded)
OBJS = ActionWithPython.o PythonCVInterface.o PythonFunction.o PlumedPythonEmbeddedModule.o
PYTHON=python
#optional, just in case you want to override python with ./configurePyCV.sh
-include Makefile.conf
#this makefiles assume that pip and pytest are installed
.PHONY: clean check check_standalone check_python all

ifeq ($(SOEXT),dylib)
SONAME_OPTION:=-Wl,-install_name
else
SONAME_OPTION:=-Wl,-soname
endif
all: pycv_here

all: PythonCVInterface.$(SOEXT)

#-fvisibility=hidden is needed for pybind11 (to not conflict with different pybind11 versions)
#I think I enforced this nearly everywhere I set up a flag for the compiler
ActionWithPython.o PythonCVInterface.o PythonFunction.o PlumedPythonEmbeddedModule.o: PYBIND11FLAG= -fvisibility=hidden

%.o: %.cpp $(DEPDIR)/%.d | $(DEPDIR)
@echo Compiling object $@
@$(CXX) -c $(DEPFLAGS) $(CPPFLAGS) $(PYBIND11FLAG) $(ADDCPPFLAGS) $(CXXFLAGS) $< -o $@


$(DEPDIR): ; @mkdir -p $@

DEPFILES := $(OBJS:%.o=$(DEPDIR)/%.d)
$(DEPFILES):
include $(wildcard $(DEPFILES))

#-Wl,--no-as-needed forces the python library to be linked, without this in a WSL does not work
#TODO: seems that $PLUMED_KERNEL is not needed, check
PythonCVInterface.$(SOEXT): $(OBJS)
@echo Linking $@
$(LDSHARED) $(SONAME_OPTION),"$(notdir $@)" $(DYNAMIC_LIBS) $(PLUMED_KERNEL) $(ADDCLDFLAGS) $^ -o $@
pycv_here: src/*.cpp src/*.h src/pycv/*.py
@echo installing pycv
$(PYTHON) -m pip install .
@touch $@

clean:
rm -f $(OBJS) PythonCVInterface.$(SOEXT)
@$(PYTHON) -m pip uninstall pycv -y
@rm -fv pycv_here

check: all
check_standalone: pycv_here
$(MAKE) -C regtest testclean
$(MAKE) -C regtest checkfail

#just in case pytest is still not installed we install it before the tests
check_python: pycv_here
@$(PYTHON) -m pip install pytest
@$(PYTHON) -m pytest -v

check: check_standalone check_python
47 changes: 15 additions & 32 deletions plugins/pycv/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,21 @@ You can see the original PyCV [here](https://giorginolab.github.io/plumed2-pycv)
[![DOI](https://joss.theoj.org/papers/10.21105/joss.01773/status.svg)](https://doi.org/10.21105/joss.01773)
[![plumID:19.075](https://www.plumed-nest.org/eggs/19/075/badge.svg)](https://www.plumed-nest.org/eggs/19/075/)

## Updating the readme for the new pip installation

**WIP**

As usual if you are not working in a virtual environment you are doing this at your own risk
`pip install .` should be enough, with a plumed version (>=2.10) avaiable with a pkg-config or in the `PATH`s.


>[!NOTE]
>On linux If you use `make` and `make check` note that the tests will find pycv only if you are working in the same python environment that you had active when compiling/installing plumed
> [!NOTE]
>We have some problem with the macs:
you may need to explicitly declare and export some environmental variables like the `PYTHON_PATH` to make pycv work when plumed is called


## Documentation

Expand Down Expand Up @@ -52,38 +67,6 @@ The interface to python as anticipated before depends on the following keywords:
If not specified INIT will default to `"plumedInit` and CALCULATE to
`"plumedCalculate"`, on the other hand, if PREPARE and UPDATE are not present, will be ignored.

## Preparation

For compiling the plugin you just need pybind11 and numpy.
I always recomend to create and ad-hoc environment for your projects:
```bash
python3 -m venv pycvenv
source ./pycvenv/bin/activate
pip install -U pip
pip install -r requirements.txt
```
The requirements.txt file is in the home of the plug in

### Standard compilation

If you have a plumed that supports plumed mklib (that will be release in the 2.10 version, but it is avaiable in the master branch) with multiple files you can simply
```bash
./standaloneCompile.sh
```

### Developer compilation

If you want to contribute to this module,
the procedure is slighly more compex:
```bash
./prepareMakeForDevelop.sh
```
will prepare a Make.inc in this directory that will be included by the Makefile.
Then simply:
```bash
make
```

#### Set up tests

If you are interested in running the test regarding this plugin you can use the same procedure as with the standard plumed, but in the subdir regtest of this plugin.
Expand Down
3 changes: 2 additions & 1 deletion plugins/pycv/astyle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
#formatted with shfmt https://github.com/mvdan/sh/releases
#checked with shellcheck

cd src || exit 1
for file in *.c *.cpp *.h *.inc.in; do

test -f "$file" || continue

echo -n "astyle $file"

../../astyle/astyle --options=../../.astyle.options <"$file" >"${file}.tmp" && {
../../../astyle/astyle --options=../../../.astyle.options <"$file" >"${file}.tmp" && {
if cmp -s "$file" "${file}.tmp"; then
echo
else
Expand Down
Loading

0 comments on commit 2d68d11

Please sign in to comment.