Transform LAMMPS Python module into package

- Moves lammps.py into its own package
- Imports entire module in __init__.py
- Changes both how legacy and CMake build systems install
- Added traditional setup.py for Python-only installation

Note: the CMake install target runs setup.py build and install
in a way that produces files in CMAKE_BINARY_DIR/python instead
of python/build. This is to maintain out-of-source compilation
support.
This commit is contained in:
Richard Berger
2020-12-15 15:11:21 -05:00
parent 1fee2add51
commit aca2eefce5
6 changed files with 60 additions and 32 deletions

View File

@ -661,7 +661,7 @@ if(BUILD_SHARED_LIBS)
add_custom_target( add_custom_target(
install-python install-python
${Python_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h ${Python_EXECUTABLE} install.py -v ${LAMMPS_SOURCE_DIR}/version.h
-m ${LAMMPS_PYTHON_DIR}/lammps.py -p ${LAMMPS_PYTHON_DIR}/lammps
-l ${CMAKE_BINARY_DIR}/liblammps${CMAKE_SHARED_LIBRARY_SUFFIX} -l ${CMAKE_BINARY_DIR}/liblammps${CMAKE_SHARED_LIBRARY_SUFFIX}
WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR}
COMMENT "Installing LAMMPS Python module") COMMENT "Installing LAMMPS Python module")
@ -691,11 +691,8 @@ if(BUILD_SHARED_LIBS OR PKG_PYTHON)
find_package(Python COMPONENTS Interpreter) find_package(Python COMPONENTS Interpreter)
endif() endif()
if (Python_EXECUTABLE) if (Python_EXECUTABLE)
execute_process(COMMAND ${Python_EXECUTABLE} file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/python)
-c "import distutils.sysconfig as cg; print(cg.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))" install(CODE "execute_process(COMMAND ${Python_EXECUTABLE} setup.py build -b ${CMAKE_BINARY_DIR}/python install --prefix=${CMAKE_INSTALL_PREFIX} WORKING_DIRECTORY ${LAMMPS_PYTHON_DIR})")
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 ${LAMMPS_PYTHON_DIR}/lammps.py DESTINATION ${PYTHON_INSTDIR})
endif() endif()
endif() endif()

View File

@ -1,42 +1,42 @@
#!/usr/bin/env python #!/usr/bin/env python
""" """
Installer script to install the LAMMPS python module and the corresponding Installer script to install the LAMMPS python package and the corresponding
shared library into either the system-wide site-packages tree, or - failing shared library into either the system-wide site-packages tree, or - failing
that - into the corresponding user tree. Called from the 'install-python' that - into the corresponding user tree. Called from the 'install-python'
build target in the conventional and CMake based build systems build target in the conventional and CMake based build systems
""" """
# copy LAMMPS shared library and lammps.py to system dirs # copy LAMMPS shared library and lammps package to system dirs
from __future__ import print_function from __future__ import print_function
import sys,os,shutil import sys,os,shutil
from argparse import ArgumentParser from argparse import ArgumentParser
parser = ArgumentParser(prog='install.py', parser = ArgumentParser(prog='install.py',
description='LAMMPS python module installer script') description='LAMMPS python package installer script')
parser.add_argument("-m", "--module", required=True, parser.add_argument("-p", "--package", required=True,
help="path to the source of the LAMMPS Python module") help="path to the LAMMPS Python package")
parser.add_argument("-l", "--lib", required=True, parser.add_argument("-l", "--lib", required=True,
help="path to the compiled LAMMPS shared library") help="path to the compiled LAMMPS shared library")
parser.add_argument("-v", "--version", required=True, parser.add_argument("-v", "--version", required=True,
help="path to the LAMMPS version.h header file") help="path to the LAMMPS version.h header file")
parser.add_argument("-d","--dir", parser.add_argument("-d","--dir",
help="Legacy custom installation folder selection for module and library") help="Legacy custom installation folder selection for package and library")
args = parser.parse_args() args = parser.parse_args()
# validate arguments and make paths absolute # validate arguments and make paths absolute
if args.module: if args.package:
if not os.path.exists(args.module): if not os.path.exists(args.package):
print( "ERROR: LAMMPS module file %s does not exist" % args.module) print( "ERROR: LAMMPS package %s does not exist" % args.package)
parser.print_help() parser.print_help()
sys.exit(1) sys.exit(1)
else: else:
args.module = os.path.abspath(args.module) args.package = os.path.abspath(args.package)
if args.lib: if args.lib:
if not os.path.exists(args.lib): if not os.path.exists(args.lib):
@ -66,9 +66,9 @@ if args.dir:
# without any special processing or additional steps to that folder # without any special processing or additional steps to that folder
if args.dir: if args.dir:
print("Copying LAMMPS Python module to custom folder %s" % args.dir) print("Copying LAMMPS Python package to custom folder %s" % args.dir)
try: try:
shutil.copyfile(args.module, os.path.join(args.dir,'lammps.py')) shutil.copytree(args.package, os.path.join(args.dir,'lammps'))
except shutil.Error: except shutil.Error:
pass # fail silently pass # fail silently
@ -81,15 +81,19 @@ if args.dir:
sys.exit() sys.exit()
# extract version string from header # extract version string from header
fp = open(args.version,'r') def get_lammps_version(header):
txt=fp.read().split('"')[1].split() with open(header, 'r') as f:
verstr=txt[0]+txt[1]+txt[2] line = f.readline()
fp.close() start_pos = line.find('"')+1
end_pos = line.find('"', start_pos)
return "".join(line[start_pos:end_pos].split())
print("Installing LAMMPS Python module version %s into site-packages folder" % verstr) verstr = get_lammps_version(args.version)
# we need to switch to the folder of the python module print("Installing LAMMPS Python package version %s into site-packages folder" % verstr)
os.chdir(os.path.dirname(args.module))
# we need to switch to the folder of the python package
os.chdir(os.path.dirname(args.package))
from distutils.core import setup from distutils.core import setup
from distutils.sysconfig import get_python_lib from distutils.sysconfig import get_python_lib
@ -103,10 +107,10 @@ try:
author = "Steve Plimpton", author = "Steve Plimpton",
author_email = "sjplimp@sandia.gov", author_email = "sjplimp@sandia.gov",
url = "https://lammps.sandia.gov", url = "https://lammps.sandia.gov",
description = "LAMMPS Molecular Dynamics Python module", description = "LAMMPS Molecular Dynamics Python package",
license = "GPL", license = "GPL",
py_modules = ["lammps"], packages=['lammps'],
data_files = [(get_python_lib(), [args.lib])]) data_files = [(os.path.join(get_python_lib(), 'lammps'), [args.lib])])
except: except:
tryuser=True tryuser=True
print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE) print ("Installation into global site-packages folder failed.\nTrying user folder %s now." % site.USER_SITE)
@ -119,9 +123,9 @@ if tryuser:
author = "Steve Plimpton", author = "Steve Plimpton",
author_email = "sjplimp@sandia.gov", author_email = "sjplimp@sandia.gov",
url = "https://lammps.sandia.gov", url = "https://lammps.sandia.gov",
description = "LAMMPS Molecular Dynamics Python module", description = "LAMMPS Molecular Dynamics Python package",
license = "GPL", license = "GPL",
py_modules = ["lammps"], packages=['lammps'],
data_files = [(site.USER_SITE, [args.lib])]) data_files = [(os.path.join(site.USER_SITE, 'lammps'), [args.lib])])
except: except:
print("Installation into user site package folder failed.") print("Installation into user site package folder failed.")

View File

@ -0,0 +1 @@
from .lammps import *

26
python/setup.py Normal file
View File

@ -0,0 +1,26 @@
# this only installs the LAMMPS python package
# it assumes the LAMMPS shared library is already installed
from distutils.core import setup
import os
LAMMPS_PYTHON_DIR = os.path.dirname(os.path.realpath(__file__))
LAMMPS_DIR = os.path.dirname(LAMMPS_PYTHON_DIR)
LAMMPS_SOURCE_DIR = os.path.join(LAMMPS_DIR, 'src')
def get_lammps_version():
with open(os.path.join(LAMMPS_SOURCE_DIR, 'version.h'), 'r') as f:
line = f.readline()
start_pos = line.find('"')+1
end_pos = line.find('"', start_pos)
return "".join(line[start_pos:end_pos].split())
setup(
name = "lammps",
version = get_lammps_version(),
author = "Steve Plimpton",
author_email = "sjplimp@sandia.gov",
url = "https://lammps.sandia.gov",
description = "LAMMPS Molecular Dynamics Python package",
license = "GPL",
packages=["lammps"]
)

View File

@ -278,7 +278,7 @@ mpi-stubs:
sinclude ../lib/python/Makefile.lammps sinclude ../lib/python/Makefile.lammps
install-python: install-python:
@$(PYTHON) ../python/install.py -v ../src/version.h \ @$(PYTHON) ../python/install.py -v ../src/version.h \
-m ../python/lammps.py -l ../src/liblammps.so -p ../python/lammps -l ../src/liblammps.so
# Create a tarball of src dir and packages # Create a tarball of src dir and packages