1# 2# This file is part of the GROMACS molecular simulation package. 3# 4# Copyright (c) 2019,2020,2021, by the GROMACS development team, led by 5# Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl, 6# and including many others, as listed in the AUTHORS file in the 7# top-level source directory and at http://www.gromacs.org. 8# 9# GROMACS is free software; you can redistribute it and/or 10# modify it under the terms of the GNU Lesser General Public License 11# as published by the Free Software Foundation; either version 2.1 12# of the License, or (at your option) any later version. 13# 14# GROMACS is distributed in the hope that it will be useful, 15# but WITHOUT ANY WARRANTY; without even the implied warranty of 16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17# Lesser General Public License for more details. 18# 19# You should have received a copy of the GNU Lesser General Public 20# License along with GROMACS; if not, see 21# http://www.gnu.org/licenses, or write to the Free Software Foundation, 22# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 23# 24# If you want to redistribute modifications to GROMACS, please 25# consider that scientific software is very special. Version 26# control is crucial - bugs must be traceable. We will be happy to 27# consider code for inclusion in the official distribution, but 28# derived work must not be called official GROMACS. Details are found 29# in the README & COPYING files - if they are missing, get the 30# official version at http://www.gromacs.org. 31# 32# To help us fund GROMACS development, we humbly ask that you cite 33# the research papers on the package. Check out http://www.gromacs.org. 34 35# Python setuptools script to build and install the gmxapi Python interface 36# from a GROMACS installation directory. 37 38# Usage note: things go smoothly when we stick to the setup.py convention of 39# having a package source directory with the same name as the package at the 40# same level as the setup.py script and only expect `pip install .` in the 41# setup.py directory. If we play with the layout more, it is hard to keep all 42# of the `pip` and `setup.py` cases working as expected. This is annoying 43# because running the Python interpreter immediately from the same directory 44# can find the uninstalled source instead of the installed package. We can 45# ease this pain by building an sdist in the enclosing CMake build scope 46# and encouraging users to `pip install the_sdist.archive`. Otherwise, we 47# just have to document that we only support full build-install of the Python 48# package from the directory containing setup.py, which may clutter that 49# directory with some artifacts. 50 51import os 52 53# Import setuptools early to avoid UserWarning from Distutils. 54# Ref: https://gitlab.com/gromacs/gromacs/-/issues/3715 55import setuptools 56 57# Allow setup.py to be run when scikit-build is not installed, such as to 58# produce source distribution archives with `python setup.py sdist` 59try: 60 from skbuild import setup 61except ImportError: 62 from distutils.core import setup 63 64usage = """ 65The `gmxapi` package requires an existing GROMACS installation, version 2020 or higher. 66To specify the GROMACS installation to use, provide a GMXTOOLCHAINDIR 67environment variable when running setup.py or `pip`. 68 69Example: 70 GMXTOOLCHAINDIR=/path/to/gromacs/share/cmake/gromacs pip install gmxapi 71 72If you have multiple builds of GROMACS, distinguished by a suffix `$SUFFIX`, the 73tool chain directory will use that suffix. 74 75Example: 76 GMXTOOLCHAINDIR=/path/to/gromacs/share/cmake/gromacs$SUFFIX pip install gmxapi 77 78In the example, `gmxapi` is downloaded automatically from pypi.org. You can 79replace `gmxapi` with a local directory or archive file to build from a source 80distribution. 81 82setup.py will use the location of GMXTOOLCHAINDIR to locate the 83gmxapi library configured during GROMACS installation. Alternatively, if 84gmxapi_DIR is provided, or if GMXRC has been "sourced", the toolchain file 85location may be deduced. Note, though, that if multiple GROMACS installations 86exist in the same location (with different suffixes) only the first one will be 87used when guessing a toolchain, because setup.py does not know which corresponds 88to the gmxapi support library. 89 90If specifying GMXTOOLCHAINDIR and gmxapi_DIR, the tool chain directory must be 91located within a subdirectory of gmxapi_DIR. 92 93Refer to project web site for complete documentation. 94 95""" 96 97 98class GmxapiInstallError(Exception): 99 """Error processing setup.py for gmxapi Python package.""" 100 101 102gmx_toolchain_dir = os.getenv('GMXTOOLCHAINDIR') 103gmxapi_DIR = os.getenv('gmxapi_DIR') 104if gmxapi_DIR is None: 105 # Infer from GMXRC exports, if available. 106 gmxapi_DIR = os.getenv('GROMACS_DIR') 107 108 109def _find_first_gromacs_suffix(directory): 110 dir_contents = os.listdir(directory) 111 for entry in dir_contents: 112 if entry.startswith('gromacs'): 113 return entry.strip('gromacs') 114 115 116if gmx_toolchain_dir is None: 117 # Try to guess from standard GMXRC environment variables. 118 if gmxapi_DIR is not None: 119 if os.path.exists(gmxapi_DIR) and os.path.isdir(gmxapi_DIR): 120 share_cmake = os.path.join(gmxapi_DIR, 'share', 'cmake') 121 suffix = _find_first_gromacs_suffix(share_cmake) 122 if suffix is not None: 123 gmx_toolchain_dir = os.path.join(share_cmake, 'gromacs' + suffix) 124 125if gmx_toolchain_dir is None: 126 print(usage) 127 raise GmxapiInstallError('Could not configure for GROMACS installation. Provide GMXTOOLCHAINDIR.') 128 129suffix = os.path.basename(gmx_toolchain_dir).strip('gromacs') 130gmx_toolchain = os.path.abspath(os.path.join(gmx_toolchain_dir, 'gromacs-toolchain' + suffix + '.cmake')) 131 132if gmxapi_DIR is None: 133 # Example: given /usr/local/gromacs/share/cmake/gromacs/gromacs-toolchain.cmake, 134 # we would want /usr/local/gromacs. 135 # Note that we could point more directly to the gmxapi-config.cmake but, 136 # so far, we have relied on CMake automatically looking into 137 # <package>_DIR/share/cmake/<package>/ for such a file. 138 # We would need a slightly different behavior for packages that link against 139 # libgromacs directly, as sample_restraint currently does. 140 gmxapi_DIR = os.path.join(os.path.dirname(gmx_toolchain), '..', '..', '..') 141 142gmxapi_DIR = os.path.abspath(gmxapi_DIR) 143 144if not os.path.exists(gmxapi_DIR) or not os.path.isdir(gmxapi_DIR): 145 print(usage) 146 raise GmxapiInstallError('Please set a valid gmxapi_DIR.') 147 148if gmxapi_DIR != os.path.commonpath([gmxapi_DIR, gmx_toolchain]): 149 raise GmxapiInstallError('GROMACS toolchain file {} is not in gmxapi_DIR {}'.format( 150 gmx_toolchain, 151 gmxapi_DIR 152 )) 153 154cmake_platform_hints = '-DCMAKE_TOOLCHAIN_FILE={}'.format(gmx_toolchain) 155# Note that <package>_ROOT is not standard until CMake 3.12 156# Reference https://cmake.org/cmake/help/latest/policy/CMP0074.html#policy:CMP0074 157cmake_gmxapi_hint = '-Dgmxapi_ROOT={}'.format(gmxapi_DIR) 158cmake_args = [cmake_platform_hints, cmake_gmxapi_hint] 159 160long_description = """gmxapi provides Python access to GROMACS molecular simulation tools. 161Operations can be connected flexibly to allow high performance simulation and 162analysis with complex control and data flows. Users can define new operations 163in C++ or Python with the same tool kit used to implement this package. 164 165This Python package requires a compatible GROMACS installation with the API 166libraries and headers. 167 168See http://gmxapi.org/ for details on installation and usage. 169""" 170 171setup( 172 name='gmxapi', 173 174 # TODO: single-source version information (currently repeated in gmxapi/version.py and CMakeLists.txt) 175 version='0.2.3', 176 python_requires='>=3.6', 177 install_requires=['networkx>=2.0', 178 'numpy>=1'], 179 180 packages=['gmxapi', 'gmxapi.simulation'], 181 package_data={'gmxapi': ['gmxconfig.json']}, 182 183 cmake_args=cmake_args, 184 185 author='M. Eric Irrgang', 186 author_email='info@gmxapi.org', 187 description='gmxapi Python interface for GROMACS', 188 long_description=long_description, 189 license='LGPL', 190 url='http://gmxapi.org/', 191 192 # The installed package will contain compiled C++ extensions that cannot be loaded 193 # directly from a zip file. 194 zip_safe=False 195) 196