1#/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2#   Copyright (c) 2011-2016 The plumed team
3#   (see the PEOPLE file at the root of the distribution for a list of names)
4#
5#   See http://www.plumed.org for more information.
6#
7#   This file is part of plumed, version 2.
8#
9#   plumed is free software: you can redistribute it and/or modify
10#   it under the terms of the GNU Lesser General Public License as published by
11#   the Free Software Foundation, either version 3 of the License, or
12#   (at your option) any later version.
13#
14#   plumed 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
17#   GNU Lesser General Public License for more details.
18#
19#   You should have received a copy of the GNU Lesser General Public License
20#   along with plumed.  If not, see <http://www.gnu.org/licenses/>.
21#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22#
23# This python routine builds an interface between plumed and python using cython
24#
25from setuptools import setup
26from setuptools import Extension
27import subprocess
28import os
29import os.path
30import sys
31from shutil import copyfile
32import platform
33from distutils.sysconfig import get_config_var
34from distutils.version import LooseVersion
35
36if sys.version_info < (3,):
37    raise ImportError("PLUMED 2.6 only supports Python 3")
38
39def is_platform_mac():
40    return sys.platform == 'darwin'
41
42if os.getenv("plumed_macports") is not None:
43    copyfile("../VERSION","VERSION")
44    try:
45        os.mkdir("include")
46    except OSError:
47        pass
48    copyfile("../src/wrapper/Plumed.h","include/Plumed.h")
49
50plumedname = os.getenv("plumed_program_name")
51if plumedname is None:
52    plumedname = "plumed"
53
54plumedversion = os.getenv("plumed_version")
55if plumedversion is None:
56    plumedversion = subprocess.check_output(['grep','-v','#','./VERSION']).decode("utf-8").rstrip()
57
58print( "Module name " + plumedname )
59print( "Version number " + plumedversion )
60
61extra_compile_args=['-D__PLUMED_HAS_DLOPEN','-D__PLUMED_WRAPPER_LINK_RUNTIME=1','-D__PLUMED_WRAPPER_CXX=1','-D__PLUMED_WRAPPER_IMPLEMENTATION=1','-D__PLUMED_WRAPPER_EXTERN=0','-D__PLUMED_WRAPPER_CXX_DEFAULT_INVALID=1']
62
63defaultkernel=os.getenv("plumed_default_kernel")
64if defaultkernel is not None:
65    extra_compile_args.append("-D__PLUMED_DEFAULT_KERNEL=" + os.path.abspath(defaultkernel))
66    print( "Hardcoded PLUMED_KERNEL " + os.path.abspath(defaultkernel))
67
68# Fixes problem with compiling the PYTHON interface in Mac OS 10.14 and higher.
69# Sets the deployment target to 10.9 when compiling on version 10.9 and above,
70# overriding distutils behaviour to target the Mac OS version python was built for.
71# This can be overridden by setting MACOSX_DEPLOYMENT_TARGET before compiling the
72# python interface.
73# This fix is taken from https://github.com/pandas-dev/pandas/pull/24274/files
74if is_platform_mac():
75    if 'MACOSX_DEPLOYMENT_TARGET' not in os.environ:
76        current_system = LooseVersion(platform.mac_ver()[0])
77        python_target = LooseVersion(get_config_var('MACOSX_DEPLOYMENT_TARGET'))
78        if python_target < '10.9' and current_system >= '10.9':
79            os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
80
81def readme():
82    with open('README.rst') as f:
83        return f.read()
84
85
86try:
87    include_dirs=[os.environ["plumed_include_dir"]]
88except KeyError:
89    include_dirs=["./include"]
90
91# allow one to force using cython with env var plumed_force_cython=yes
92USE_CYTHON = False
93try:
94    if(os.environ["plumed_force_cython"]=="yes"):
95        print('plumed_force_cython=yes')
96        USE_CYTHON = True
97except KeyError:
98    pass
99
100# if plumed.cpp is available, do not need cython
101if not USE_CYTHON:
102    if not os.path.isfile("plumed.cpp"):
103        print('plumed.cpp not found, cython is needed')
104        USE_CYTHON = True
105
106# try to import cython
107if USE_CYTHON:
108    try:
109        print('importing cython')
110        from Cython.Build import cythonize
111        extension="pyx"
112    except ImportError:
113        print('Error: building ' + plumedname + ' requires cython. Please install it first with pip install cython')
114        sys.exit(-1)
115else:
116    print('using available plumed.cpp file')
117    extension="cpp"
118
119ext_modules=[Extension(
120     name=plumedname,
121     sources=["plumed." + extension],
122     language="c++",
123     include_dirs=include_dirs,
124     extra_compile_args=extra_compile_args
125  )]
126
127if USE_CYTHON:
128    ext_modules=cythonize(ext_modules,language_level=3)
129
130setup(
131  name=plumedname,
132  version=plumedversion,
133  description='Python interface to PLUMED',
134  long_description=readme(),
135  classifiers=[
136          'Development Status :: 4 - Beta',
137          'Intended Audience :: Science/Research',
138          'Topic :: Scientific/Engineering :: Bio-Informatics',
139          'Topic :: Scientific/Engineering :: Chemistry',
140          'Topic :: Scientific/Engineering :: Physics',
141          'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)',
142          'Programming Language :: Python :: 3',
143          'Programming Language :: Python :: 3.6',
144          'Programming Language :: Python :: 3.7',
145  ],
146  author='Gareth A. Tribello',
147  author_email='plumed-users@googlegroups.com',
148  url='http://www.plumed.org',
149  ext_modules = ext_modules,
150  zip_safe=False,
151  test_suite='nose.collector',
152  python_requires='>=3'
153)
154