diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 2adf7d83f..dc3a48680 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,11 +18,13 @@ - Improvements: - - Add ``fall_back_on_python`` boolean keyword argument to + - Added ``fall_back_on_python`` boolean keyword argument to ``ForceConstants.calculate_qpoint_phonon_modes`` to control whether the Python implementation is used as a fallback to the C extension or not, see `#35 `_ + - Added ``--python-only`` option to ``setup.py`` to enable install + without the C extension - Bug fixes: diff --git a/doc/source/index.rst b/doc/source/index.rst index de4d418b0..68908e556 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -56,18 +56,14 @@ If you don't require plotting or reading of Phonopy files, just use: pip install . -Installing the C extension (optional) -===================================== -Euphonic has an optional C extension, which can lead to increased performance -and enable use of multiple cores when interpolating phonons. By default -Euphonic will attempt to install this extension, but will print a warning and -fall back to the pure Python version if this fails. To determine if the C -extension is installing properly and investigate any problems, it is best to -increase pip's verbosity: +Installing the C extension +========================== -.. code-block:: bash - - pip install -vvv euphonic +By default, Euphonic will attempt to build and install the C extension, +which can lead to increased performance and enable use of multiple cores when +interpolating phonons. See below for information on installing the extension +for different platforms. If you are having trouble installing the C extension +and don't require it, see `Installing Euphonic without the C extension`_ **Windows** @@ -94,6 +90,21 @@ before running pip install run: brew install llvm +Installing Euphonic without the C extension +=========================================== + +If you don't need the extra performance the C extension provides, you can +install the Python parts only with: + +.. code-block:: bash + + pip install --install-option="--python-only" euphonic + +Note that using this option disables the use of wheels which, if they haven't +been installed already, actually makes installing other packages such as Numpy +more difficult. The easiest way around this is running the usual install +command first (which will install all the dependencies), then running again +with the ``--install-option="--python-only"`` option. .. toctree:: :hidden: diff --git a/setup.py b/setup.py index b8002cb13..106873707 100644 --- a/setup.py +++ b/setup.py @@ -1,50 +1,63 @@ import versioneer try: from setuptools import setup, find_packages, Extension + from setuptools.command.install import install except ImportError: from distutils.core import setup, find_packages, Extension + from distutils.command.install import install -def run_setup(build_c=True): +class InstallCommand(install): + user_options = install.user_options + [('python-only', None, 'Install only Python')] + + def initialize_options(self): + install.initialize_options(self) + self.python_only = 0 + + def finalize_options(self): + install.finalize_options(self) + if not bool(self.python_only): + self.distribution.ext_modules = [get_c_extension()] - if build_c: - import os - import numpy as np - from sys import platform - import subprocess - include_dirs = [np.get_include(), 'c'] - sources = ['c/_euphonic.c', 'c/dyn_mat.c', 'c/util.c', 'c/py_util.c', - 'c/load_libs.c'] - if platform == 'win32': - # Windows - assume MSVC compiler - compile_args = ['/openmp'] - link_args = None - elif platform == 'darwin': - # OSX - assume brew install llvm - brew_prefix_cmd_return = subprocess.run(["brew", "--prefix"], - stdout=subprocess.PIPE) - brew_prefix = brew_prefix_cmd_return.stdout.decode("utf-8").strip() - os.environ['CC'] = '{}/opt/llvm/bin/clang'.format(brew_prefix) - compile_args = ['-fopenmp'] - link_args = ['-L{}/opt/llvm/lib'.format(brew_prefix), '-fopenmp'] - else: - # Linux - assume gcc - os.environ['CC'] = 'gcc' - compile_args = ['-fopenmp'] - link_args = ['-fopenmp'] - euphonic_extension = Extension( - 'euphonic._euphonic', - extra_compile_args=compile_args, - extra_link_args=link_args, - include_dirs=include_dirs, - sources=sources - ) - ext_modules = [euphonic_extension] +def get_c_extension(): + import os + import numpy as np + from sys import platform + import subprocess + include_dirs = [np.get_include(), 'c'] + sources = ['c/_euphonic.c', 'c/dyn_mat.c', 'c/util.c', 'c/py_util.c', + 'c/load_libs.c'] + if platform == 'win32': + # Windows - assume MSVC compiler + compile_args = ['/openmp'] + link_args = None + elif platform == 'darwin': + # OSX - assume brew install llvm + brew_prefix_cmd_return = subprocess.run(["brew", "--prefix"], + stdout=subprocess.PIPE) + brew_prefix = brew_prefix_cmd_return.stdout.decode("utf-8").strip() + os.environ['CC'] = '{}/opt/llvm/bin/clang'.format(brew_prefix) + compile_args = ['-fopenmp'] + link_args = ['-L{}/opt/llvm/lib'.format(brew_prefix), '-fopenmp'] else: - ext_modules = None + # Linux - assume gcc + os.environ['CC'] = 'gcc' + compile_args = ['-fopenmp'] + link_args = ['-fopenmp'] + + euphonic_c_extension = Extension( + 'euphonic._euphonic', + extra_compile_args=compile_args, + extra_link_args=link_args, + include_dirs=include_dirs, + sources=sources + ) + return euphonic_c_extension +def run_setup(build_c=True): + with open('README.rst', 'r') as f: long_description = f.read() @@ -55,10 +68,13 @@ def run_setup(build_c=True): 'scripts/dos.py', 'scripts/optimise_eta.py'] + cmdclass = versioneer.get_cmdclass() + cmdclass['install'] = InstallCommand + setup( name='euphonic', version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), + cmdclass=cmdclass, author='Rebecca Fair', author_email='rebecca.fair@stfc.ac.uk', description=( @@ -79,17 +95,7 @@ def run_setup(build_c=True): 'matplotlib': ['matplotlib>=1.4.2'], 'phonopy_reader': ['h5py>=2.9.0', 'PyYAML>=5.1.2'] }, - scripts=scripts, - ext_modules=ext_modules + scripts=scripts ) - -try: - run_setup() -except: - print('*'*79) - print(('Failed to build Euphonic C extension, installing pure ' - 'Python version instead')) - print('*'*79) - print("Unexpected error: {}".format(sys.exc_info()[0])) - run_setup(build_c=False) +run_setup()