mirror of https://github.com/lammps/lammps.git
Merge pull request #1375 from akohlmey/install-python-for-cmake
Refactor python module installer and add install-python target to CMake
This commit is contained in:
commit
e63d2cee87
|
@ -381,19 +381,10 @@ if(PKG_MSCG OR PKG_USER-ATC OR PKG_USER-AWPMD OR PKG_USER-QUIP OR PKG_LATTE)
|
|||
endif()
|
||||
|
||||
if(PKG_PYTHON)
|
||||
find_package(PythonInterp REQUIRED)
|
||||
find_package(PythonLibs REQUIRED)
|
||||
add_definitions(-DLMP_PYTHON)
|
||||
include_directories(${PYTHON_INCLUDE_DIR})
|
||||
list(APPEND LAMMPS_LINK_LIBS ${PYTHON_LIBRARY})
|
||||
if(BUILD_LIB AND BUILD_SHARED_LIBS)
|
||||
if(NOT PYTHON_INSTDIR)
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
-c "import distutils.sysconfig as cg; print(cg.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))"
|
||||
OUTPUT_VARIABLE PYTHON_INSTDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
endif()
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../python/lammps.py DESTINATION ${PYTHON_INSTDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
find_package(JPEG QUIET)
|
||||
|
@ -1467,6 +1458,49 @@ install(
|
|||
DESTINATION ${CMAKE_INSTALL_SYSCONFDIR}/profile.d
|
||||
)
|
||||
|
||||
###############################################################################
|
||||
# Install LAMMPS lib and python module into site-packages folder with
|
||||
# "install-python" target. Behaves exactly like "make install-python" for
|
||||
# conventional build. Only available, if a shared library is built.
|
||||
# This is primarily for people that only want to use the Python wrapper.
|
||||
###############################################################################
|
||||
if(BUILD_LIB AND BUILD_SHARED_LIBS)
|
||||
find_package(PythonInterp)
|
||||
if (PYTHONINTERP_FOUND)
|
||||
add_custom_target(
|
||||
install-python
|
||||
${PYTHON_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h
|
||||
-m ${CMAKE_CURRENT_SOURCE_DIR}/../python/lammps.py
|
||||
-l ${CMAKE_BINARY_DIR}/liblammps${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../python
|
||||
COMMENT "Installing LAMMPS Python module")
|
||||
else()
|
||||
add_custom_target(
|
||||
install-python
|
||||
${CMAKE_COMMAND} -E echo "Must have Python installed to install the LAMMPS Python module")
|
||||
endif()
|
||||
else()
|
||||
add_custom_target(
|
||||
install-python
|
||||
${CMAKE_COMMAND} -E echo "Must build LAMMPS as a shared library to use the Python module")
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
# Add LAMMPS python module to "install" target. This is taylored for building
|
||||
# LAMMPS for package managers and with different prefix settings.
|
||||
# This requires either a shared library or that the PYTHON package is included.
|
||||
###############################################################################
|
||||
if((BUILD_LIB AND BUILD_SHARED_LIBS) OR (PKG_PYTHON))
|
||||
find_package(PythonInterp)
|
||||
if (PYTHONINTERP_FOUND)
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE}
|
||||
-c "import distutils.sysconfig as cg; print(cg.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))"
|
||||
OUTPUT_VARIABLE PYTHON_DEFAULT_INSTDIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
set(PYTHON_INSTDIR ${PYTHON_DEFAULT_INSTDIR} CACHE PATH "Installation folder for LAMMPS Python module")
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../python/lammps.py DESTINATION ${PYTHON_INSTDIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###############################################################################
|
||||
# Testing
|
||||
#
|
||||
|
|
|
@ -57,6 +57,17 @@ library is then loaded by the Python interface. In this example we enable the
|
|||
MOLECULE package and compile LAMMPS with C++ exceptions, PNG, JPEG and FFMPEG
|
||||
output support enabled.
|
||||
|
||||
Step 1a: For the CMake based build system, the steps are:
|
||||
|
||||
mkdir $LAMMPS_DIR/build-shared
|
||||
cd $LAMMPS_DIR/build-shared :pre
|
||||
|
||||
# MPI, PNG, Jpeg, FFMPEG are auto-detected
|
||||
cmake ../cmake -DPKG_MOLECULE=yes -DLAMMPS_EXCEPTIONS=yes -DBUILD_LIB=yes -DBUILD_SHARED_LIBS=yes
|
||||
make :pre
|
||||
|
||||
Step 1b: For the legacy, make based build system, the steps are:
|
||||
|
||||
cd $LAMMPS_DIR/src :pre
|
||||
|
||||
# add packages if necessary
|
||||
|
@ -68,10 +79,9 @@ make mpi mode=shlib LMP_INC="-DLAMMPS_PNG -DLAMMPS_JPEG -DLAMMPS_FFMPEG -DLAMMPS
|
|||
Step 2: Installing the LAMMPS Python package :h6
|
||||
|
||||
PyLammps is part of the lammps Python package. To install it simply install
|
||||
that package into your current Python installation.
|
||||
that package into your current Python installation with:
|
||||
|
||||
cd $LAMMPS_DIR/python
|
||||
python install.py :pre
|
||||
make install-python :pre
|
||||
|
||||
NOTE: Recompiling the shared library requires re-installing the Python package
|
||||
|
||||
|
@ -94,14 +104,21 @@ apt-get install python-virtualenv :pre
|
|||
|
||||
Creating a virtualenv with lammps installed :h6
|
||||
|
||||
# create virtualenv name 'testing' :pre
|
||||
# create virtualenv named 'testing'
|
||||
virtualenv $HOME/python/testing :pre
|
||||
|
||||
# activate 'testing' environment
|
||||
source testing/bin/activate :pre
|
||||
source $HOME/python/testing/bin/activate :pre
|
||||
|
||||
Now configure and compile the LAMMPS shared library as outlined above.
|
||||
When using CMake and the shared library has already been build, you
|
||||
need to re-run CMake to update the location of the python executable
|
||||
to the location in the virtual environment with:
|
||||
|
||||
cmake . -DPYTHON_EXECUTABLE=$(which python) :pre
|
||||
|
||||
# install LAMMPS package in virtualenv
|
||||
(testing) cd $LAMMPS_DIR/python
|
||||
(testing) python install.py :pre
|
||||
(testing) make install-python :pre
|
||||
|
||||
# install other useful packages
|
||||
(testing) pip install matplotlib jupyter mpi4py :pre
|
||||
|
|
|
@ -12,16 +12,23 @@ Installing LAMMPS in Python :h3
|
|||
For Python to invoke LAMMPS, there are 2 files it needs to know about:
|
||||
|
||||
python/lammps.py
|
||||
src/liblammps.so :ul
|
||||
liblammps.so or liblammps.dylib :ul
|
||||
|
||||
Lammps.py is the Python wrapper on the LAMMPS library interface.
|
||||
Liblammps.so is the shared LAMMPS library that Python loads, as
|
||||
described above.
|
||||
The python source code in lammps.py is the Python wrapper on the
|
||||
LAMMPS library interface. The liblammps.so or liblammps.dylib file
|
||||
is the shared LAMMPS library that Python loads dynamically.
|
||||
|
||||
You can insure Python can find these files in one of two ways:
|
||||
You can achieve that Python can find these files in one of two ways:
|
||||
|
||||
set two environment variables
|
||||
run the python/install.py script :ul
|
||||
set two environment variables pointing to the location in the source tree
|
||||
run "make install-python" or run the python/install.py script explicitly :ul
|
||||
|
||||
When calling "make install-python" LAMMPS will try to install the
|
||||
python module and the shared library into the python site-packages folders;
|
||||
either the system-wide ones, or the local users ones (in case of insufficient
|
||||
permissions for the global install). Python will then find the module
|
||||
and shared library file automatically. The exact location of these folders
|
||||
depends on your python version and your operating system.
|
||||
|
||||
If you set the paths to these files as environment variables, you only
|
||||
have to do it once. For the csh or tcsh shells, add something like
|
||||
|
@ -30,42 +37,28 @@ this to your ~/.cshrc file, one line for each of the two files:
|
|||
setenv PYTHONPATH $\{PYTHONPATH\}:/home/sjplimp/lammps/python
|
||||
setenv LD_LIBRARY_PATH $\{LD_LIBRARY_PATH\}:/home/sjplimp/lammps/src :pre
|
||||
|
||||
If you use the python/install.py script, you need to invoke it every
|
||||
time you rebuild LAMMPS (as a shared library) or make changes to the
|
||||
python/lammps.py file.
|
||||
On MacOSX you may also need to set DYLD_LIBRARY_PATH accordingly.
|
||||
For Bourne/Korn shells accordingly into the corresponding files using
|
||||
the "export" shell builtin.
|
||||
|
||||
You can invoke install.py from the python directory as
|
||||
If you use "make install-python" or the python/install.py script, you need
|
||||
to invoke it every time you rebuild LAMMPS (as a shared library) or
|
||||
make changes to the python/lammps.py file, so that the site-packages
|
||||
files are updated with the new version.
|
||||
|
||||
% python install.py \[libdir\] \[pydir\] :pre
|
||||
If the default settings of "make install-python" are not what you want,
|
||||
you can invoke install.py from the python directory manually as
|
||||
|
||||
The optional libdir is where to copy the LAMMPS shared library to; the
|
||||
default is /usr/local/lib. The optional pydir is where to copy the
|
||||
lammps.py file to; the default is the site-packages directory of the
|
||||
version of Python that is running the install script.
|
||||
% python install.py -m \<python module\> -l <shared library> -v <version.h file> \[-d \<pydir\>\] :pre
|
||||
|
||||
Note that libdir must be a location that is in your default
|
||||
LD_LIBRARY_PATH, like /usr/local/lib or /usr/lib. And pydir must be a
|
||||
location that Python looks in by default for imported modules, like
|
||||
its site-packages dir. If you want to copy these files to
|
||||
non-standard locations, such as within your own user space, you will
|
||||
need to set your PYTHONPATH and LD_LIBRARY_PATH environment variables
|
||||
accordingly, as above.
|
||||
The -m flag points to the lammps.py python module file to be installed,
|
||||
the -l flag points to the LAMMPS shared library file to be installed,
|
||||
the -v flag points to the version.h file in the LAMMPS source
|
||||
and the optional -d flag to a custom (legacy) installation folder :ul
|
||||
|
||||
If the install.py script does not allow you to copy files into system
|
||||
directories, prefix the python command with "sudo". If you do this,
|
||||
make sure that the Python that root runs is the same as the Python you
|
||||
run. E.g. you may need to do something like
|
||||
|
||||
% sudo /usr/local/bin/python install.py \[libdir\] \[pydir\] :pre
|
||||
|
||||
You can also invoke install.py from the make command in the src
|
||||
directory as
|
||||
|
||||
% make install-python :pre
|
||||
|
||||
In this mode you cannot append optional arguments. Again, you may
|
||||
need to prefix this with "sudo". In this mode you cannot control
|
||||
which Python is invoked by root.
|
||||
If you use a legacy installation folder, you will need to set your
|
||||
PYTHONPATH and LD_LIBRARY_PATH (and/or DYLD_LIBRARY_PATH) environment
|
||||
variables accordingly, as described above.
|
||||
|
||||
Note that if you want Python to be able to load different versions of
|
||||
the LAMMPS shared library (see "this section"_Python_shlib.html), you will
|
||||
|
|
|
@ -13,11 +13,11 @@ Overview of Python and LAMMPS :h3
|
|||
LAMMPS can work together with Python in three ways. First, Python can
|
||||
wrap LAMMPS through the its "library interface"_Howto_library.html, so
|
||||
that a Python script can create one or more instances of LAMMPS and
|
||||
launch one or more simulations. In Python lingo, this is "extending"
|
||||
Python with LAMMPS.
|
||||
launch one or more simulations. In Python lingo, this is called
|
||||
"extending" Python with a LAMMPS module.
|
||||
|
||||
Second, a lower-level Python interface can be used indirectly through
|
||||
provided PyLammps and IPyLammps wrapper classes, written in Python.
|
||||
the provided PyLammps and IPyLammps wrapper classes, written in Python.
|
||||
These wrappers try to simplify the usage of LAMMPS in Python by
|
||||
providing an object-based interface to common LAMMPS functionality.
|
||||
They also reduces the amount of code necessary to parameterize LAMMPS
|
||||
|
@ -25,11 +25,12 @@ scripts through Python and make variables and computes directly
|
|||
accessible.
|
||||
|
||||
Third, LAMMPS can use the Python interpreter, so that a LAMMPS
|
||||
input script can invoke Python code directly, and pass information
|
||||
back-and-forth between the input script and Python functions you
|
||||
write. This Python code can also callback to LAMMPS to query or change
|
||||
its attributes. In Python lingo, this is "embedding" Python in
|
||||
LAMMPS. When used in this mode, Python can perform operations that
|
||||
the simple LAMMPS input script syntax cannot.
|
||||
input script or styles can invoke Python code directly, and pass
|
||||
information back-and-forth between the input script and Python
|
||||
functions you write. This Python code can also callback to LAMMPS
|
||||
to query or change its attributes through the LAMMPS Python module
|
||||
mentioned above. In Python lingo, this is "embedding" Python in
|
||||
LAMMPS. When used in this mode, Python can perform script operations
|
||||
that the simple LAMMPS input script syntax can not.
|
||||
|
||||
|
||||
|
|
|
@ -250,6 +250,7 @@ Boresch
|
|||
Botero
|
||||
Botu
|
||||
Bouguet
|
||||
Bourne
|
||||
boxcolor
|
||||
bp
|
||||
bpls
|
||||
|
@ -627,6 +628,7 @@ dVx
|
|||
dW
|
||||
dx
|
||||
dy
|
||||
dylib
|
||||
dyn
|
||||
dyne
|
||||
dynes
|
||||
|
@ -1298,6 +1300,7 @@ Kondor
|
|||
konglt
|
||||
Koning
|
||||
Kooser
|
||||
Korn
|
||||
Koskinen
|
||||
Koster
|
||||
Kosztin
|
||||
|
|
|
@ -9,12 +9,12 @@ doc/Section_python.html and in doc/Section_start.html#start_5.
|
|||
Basically you need to follow these steps in the src directory:
|
||||
|
||||
% make g++ mode=shlib # build for whatever machine target you wish
|
||||
% make install-python # may need to do this via sudo
|
||||
% make install-python # install into site-packages folder
|
||||
|
||||
You can replace the last step by a one-time setting of environment
|
||||
variables in your shell script. Or you can run the python/install.py
|
||||
script directly to give you more control over where the two relevant
|
||||
files are installed. See doc/Section_python.html for details.
|
||||
files are installed. See doc/Python_install.html for details.
|
||||
|
||||
You should then be able to launch Python and instantiate an instance
|
||||
of LAMMPS:
|
||||
|
|
|
@ -1,56 +1,96 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# copy LAMMPS src/liblammps.so and lammps.py to system dirs
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
instructions = """
|
||||
Syntax: python install.py [-h] [pydir]
|
||||
pydir = target dir for lammps.py and liblammps.so
|
||||
default = Python site-packages dir
|
||||
"""
|
||||
Installer script to install the LAMMPS python module and the corresponding
|
||||
shared library into either the system-wide site-packages tree, or - failing
|
||||
that - into the corresponding user tree. Called from the 'install-python'
|
||||
build target in the conventional and CMake based build systems
|
||||
"""
|
||||
|
||||
# copy LAMMPS shared library and lammps.py to system dirs
|
||||
|
||||
from __future__ import print_function
|
||||
import sys,os,shutil
|
||||
from argparse import ArgumentParser
|
||||
|
||||
if (len(sys.argv) > 1 and sys.argv[1] == "-h") or len(sys.argv) > 2:
|
||||
print(instructions)
|
||||
sys.exit()
|
||||
parser = ArgumentParser(prog='install.py',
|
||||
description='LAMMPS python module installer script')
|
||||
|
||||
if len(sys.argv) == 2: pydir = sys.argv[1]
|
||||
else: pydir = ""
|
||||
parser.add_argument("-m", "--module", required=True,
|
||||
help="path to the source of the LAMMPS Python module")
|
||||
parser.add_argument("-l", "--lib", required=True,
|
||||
help="path to the compiled LAMMPS shared library")
|
||||
parser.add_argument("-v", "--version", required=True,
|
||||
help="path to the LAMMPS version.h header file")
|
||||
|
||||
# copy lammps.py to pydir if it exists
|
||||
# if pydir not specified, install in site-packages via distutils setup()
|
||||
parser.add_argument("-d","--dir",
|
||||
help="Legacy custom installation folder selection for module and library")
|
||||
|
||||
if pydir:
|
||||
if not os.path.isdir(pydir):
|
||||
print( "ERROR: pydir %s does not exist" % pydir)
|
||||
sys.exit()
|
||||
str = "cp ../python/lammps.py %s" % pydir
|
||||
print(str)
|
||||
args = parser.parse_args()
|
||||
|
||||
# validate arguments and make paths absolute
|
||||
|
||||
if args.module:
|
||||
if not os.path.exists(args.module):
|
||||
print( "ERROR: LAMMPS module file %s does not exist" % args.module)
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
else:
|
||||
args.module = os.path.abspath(args.module)
|
||||
|
||||
if args.lib:
|
||||
if not os.path.exists(args.lib):
|
||||
print( "ERROR: LAMMPS shared library %s does not exist" % args.lib)
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
else:
|
||||
args.lib = os.path.abspath(args.lib)
|
||||
|
||||
if args.version:
|
||||
if not os.path.exists(args.version):
|
||||
print( "ERROR: LAMMPS version header file %s does not exist" % args.version)
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
else:
|
||||
args.version = os.path.abspath(args.version)
|
||||
|
||||
if args.dir:
|
||||
if not os.path.isdir(args.dir):
|
||||
print( "ERROR: Installation folder %s does not exist" % args.dir)
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
else:
|
||||
args.dir = os.path.abspath(args.dir)
|
||||
|
||||
# if a custom directory is given, we copy the files directly
|
||||
# without any special processing or additional steps to that folder
|
||||
|
||||
if args.dir:
|
||||
print("Copying LAMMPS Python module to custom folder %s" % args.dir)
|
||||
try:
|
||||
shutil.copyfile("../python/lammps.py", os.path.join(pydir,'lammps.py') )
|
||||
shutil.copyfile(args.module, os.path.join(args.dir,'lammps.py'))
|
||||
except shutil.Error:
|
||||
pass # source and destination are identical
|
||||
pass # fail silently
|
||||
|
||||
str = "cp ../src/liblammps.so %s" % pydir
|
||||
print(str)
|
||||
print("Copying LAMMPS shared library to custom folder %s" % args.dir)
|
||||
try:
|
||||
shutil.copyfile("../src/liblammps.so", os.path.join(pydir,"liblammps.so") )
|
||||
shutil.copyfile(args.lib, os.path.join(args.dir,os.path.basename(args.lib)))
|
||||
except shutil.Error:
|
||||
pass # source and destination are identical
|
||||
sys.exit()
|
||||
|
||||
print("installing lammps.py in Python site-packages dir")
|
||||
pass # fail silently
|
||||
|
||||
os.chdir('../python') # in case invoked via make in src dir
|
||||
sys.exit()
|
||||
|
||||
# extract version string from header
|
||||
fp = open('../src/version.h','r')
|
||||
fp = open(args.version,'r')
|
||||
txt=fp.read().split('"')[1].split()
|
||||
verstr=txt[0]+txt[1]+txt[2]
|
||||
fp.close()
|
||||
|
||||
print("Installing LAMMPS Python module version %s into site-packages folder" % verstr)
|
||||
|
||||
# we need to switch to the folder of the python module
|
||||
os.chdir(os.path.dirname(args.module))
|
||||
|
||||
from distutils.core import setup
|
||||
from distutils.sysconfig import get_python_lib
|
||||
import site
|
||||
|
@ -62,28 +102,26 @@ try:
|
|||
version = verstr,
|
||||
author = "Steve Plimpton",
|
||||
author_email = "sjplimp@sandia.gov",
|
||||
url = "http://lammps.sandia.gov",
|
||||
description = "LAMMPS molecular dynamics library",
|
||||
url = "https://lammps.sandia.gov",
|
||||
description = "LAMMPS Molecular Dynamics Python module",
|
||||
license = "GPL",
|
||||
py_modules = ["lammps"],
|
||||
data_files = [(get_python_lib(), ["../src/liblammps.so"])])
|
||||
data_files = [(get_python_lib(), [args.lib])])
|
||||
except:
|
||||
tryuser=True
|
||||
print ("Installation into global site-packages dir failed.\nTrying user site dir %s now." % site.USER_SITE)
|
||||
|
||||
print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE)
|
||||
|
||||
if tryuser:
|
||||
try:
|
||||
sys.argv = ["setup.py","install","--user"] # as if had run "python setup.py install --user"
|
||||
setup(name = "lammps",
|
||||
version = verstr,
|
||||
author = "Steve Plimpton",
|
||||
author_email = "sjplimp@sandia.gov",
|
||||
url = "http://lammps.sandia.gov",
|
||||
description = "LAMMPS molecular dynamics library",
|
||||
py_modules = ["lammps"],
|
||||
data_files = [(site.USER_SITE, ["../src/liblammps.so"])])
|
||||
except:
|
||||
print("Installation into user site package dir failed.\nGo to ../python and install manually.")
|
||||
|
||||
|
||||
|
||||
version = verstr,
|
||||
author = "Steve Plimpton",
|
||||
author_email = "sjplimp@sandia.gov",
|
||||
url = "https://lammps.sandia.gov",
|
||||
description = "LAMMPS Molecular Dynamics Python module",
|
||||
license = "GPL",
|
||||
py_modules = ["lammps"],
|
||||
data_files = [(site.USER_SITE, [args.lib])])
|
||||
except:
|
||||
print("Installation into user site package folder failed.")
|
||||
|
|
|
@ -275,7 +275,8 @@ mpi-stubs:
|
|||
|
||||
sinclude ../lib/python/Makefile.lammps
|
||||
install-python:
|
||||
@$(PYTHON) ../python/install.py
|
||||
@$(PYTHON) ../python/install.py -v ../src/version.h \
|
||||
-m ../python/lammps.py -l ../src/liblammps.so
|
||||
|
||||
# Create a tarball of src dir and packages
|
||||
|
||||
|
|
Loading…
Reference in New Issue