Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor setup.py #229

Merged
merged 12 commits into from Mar 10, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -72,7 +72,7 @@ jobs:
linux-wheels:
working_directory: ~/linux-wheels
docker:
- image: circleci/python:3.6.8-stretch
- image: circleci/python:3.6.12-stretch
environment:
CIBW_SKIP: "cp27-* cp34-* cp35-* *i686"
CIBW_BEFORE_BUILD_LINUX: curl -OsL https://gitlab.com/libeigen/eigen/-/archive/3.3.7/eigen-3.3.7.tar.gz && tar xzf eigen-3.3.7.tar.gz eigen-3.3.7/Eigen --strip-components 1 && cp -rf Eigen {project}/include && pip install numpy scipy cython
Expand Down
330 changes: 161 additions & 169 deletions setup.py
@@ -1,169 +1,161 @@
# Copyright 2019 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#!/usr/bin/env python3
import sys
import os
import platform

from setuptools import find_packages


with open("thewalrus/_version.py") as f:
version = f.readlines()[-1].split()[-1].strip("\"'")


requirements = [
"numpy",
"scipy>=1.2.1",
"numba>=0.49.1",
"dask[delayed]",
"sympy>=1.5.1",
"repoze.lru>=0.7"
]


setup_requirements = [
"numpy"
]


BUILD_EXT = True

try:
import numpy as np
from numpy.distutils.core import setup
from numpy.distutils.extension import Extension
except ImportError:
raise ImportError("ERROR: NumPy needs to be installed first. "
"You can install it with pip:"
"\n\npip install numpy")


if BUILD_EXT:

USE_CYTHON = True
try:
from Cython.Build import cythonize
ext = 'pyx'
except:
def cythonize(x, compile_time_env=None):
return x

USE_CYTHON = False
cythonize = cythonize
ext = 'cpp'


library_default = ""
USE_OPENMP = True
EIGEN_INCLUDE = [os.environ.get("EIGEN_INCLUDE_DIR", ""), "/usr/local/include/eigen3", "/usr/include/eigen3"]

LD_LIBRARY_PATH = os.environ.get('LD_LIBRARY_PATH', library_default).split(":")
C_INCLUDE_PATH = os.environ.get('C_INCLUDE_PATH', "").split(":") + [np.get_include()] + EIGEN_INCLUDE + ["include"]

LD_LIBRARY_PATH = [i for i in LD_LIBRARY_PATH if i]
libraries = []

if platform.system() == 'Windows':
USE_OPENMP = False
cflags_default = "-static -O3 -Wall -fPIC"
extra_link_args_CPP = ["-std=c++14 -static", "-static-libgfortran", "-static-libgcc"]
elif platform.system() == 'Darwin':
cflags_default = "-O3 -Wall -fPIC -shared -Xpreprocessor -fopenmp -lomp -mmacosx-version-min=10.9"
libraries += ["omp"]
extra_link_args_CPP = ['-Xpreprocessor -fopenmp -lomp']
extra_include = ['/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/']
C_INCLUDE_PATH += ['/usr/local/opt/libomp/include']
LD_LIBRARY_PATH += ['/usr/local/opt/libomp/lib']
else:
cflags_default = "-O3 -Wall -fPIC -shared -fopenmp"
extra_link_args_CPP = ['-fopenmp']

CFLAGS = os.environ.get('CFLAGS', cflags_default).split() + ['-I{}'.format(np.get_include())]

USE_LAPACK = False
if os.environ.get("USE_LAPACK", ""):
USE_LAPACK = True
CFLAGS += [" -llapacke -DLAPACKE=1"]
libraries += ["lapacke"]
extra_link_args_CPP[0] += " -llapacke"

if os.environ.get("USE_OPENBLAS", ""):
USE_LAPACK = True
CFLAGS += [" -lopenblas -DLAPACKE=1"]
libraries += ["openblas"]
extra_link_args_CPP[0] += " -lopenblas"

extensions = cythonize([
Extension("libwalrus",
sources=["thewalrus/libwalrus."+ext,],
depends=["include/libwalrus.hpp",
"include/eigenvalue_hafnian.hpp",
"include/recursive_hafnian.hpp",
"include/repeated_hafnian.hpp",
"include/hafnian_approx.hpp",
"include/torontonian.hpp",
"include/permanent.hpp",
"include/hermite_multidimensional.hpp",
"include/stdafx.h",
"include/fsum.hpp"],
include_dirs=C_INCLUDE_PATH,
library_dirs=['/usr/lib', '/usr/local/lib'] + LD_LIBRARY_PATH,
libraries=libraries,
language="c++",
extra_compile_args=["-std=c++11"] + CFLAGS,
extra_link_args=extra_link_args_CPP)
], compile_time_env={'_OPENMP': USE_OPENMP, 'LAPACKE': USE_LAPACK})
else:
extensions = []


info = {
'name': 'thewalrus',
'version': version,
'maintainer': 'Xanadu Inc.',
'maintainer_email': 'nicolas@xanadu.ai',
'url': 'https://github.com/XanaduAI/thewalrus',
'license': 'Apache License 2.0',
'packages': find_packages(where="."),
'description': 'Open source library for hafnian calculation',
'long_description': open('README.rst').read(),
'provides': ["thewalrus"],
'install_requires': requirements,
'setup_requires': setup_requirements,
'ext_modules': extensions,
'ext_package': 'thewalrus'
}

classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX :: Linux",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3 :: Only',
"Topic :: Scientific/Engineering :: Physics"
]

setup(classifiers=classifiers, **(info))
# Copyright 2019 Xanadu Quantum Technologies Inc.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

#!/usr/bin/env python3
import os
import platform

from setuptools import find_packages

try:
import numpy as np
from numpy.distutils.core import setup
from numpy.distutils.extension import Extension
except ImportError as exc:
raise ImportError(
"Numpy must be installed to build The Walrus."
"You can install it with pip:"
"\n\npip install numpy"
) from exc


BUILD_EXT = True


def build_extensions():

if not BUILD_EXT:
return []

try:
from Cython.Build import cythonize
except ImportError as exc:
raise ImportError(
"Cython must be installed to build the extension."
"You can install it with pip"
"\n\npip install cython"
) from exc

CFLAGS = os.environ.get("CFLAGS", "-O3 -Wall")

USE_OPENBLAS = bool(os.environ.get("USE_OPENBLAS"))
USE_LAPACK = bool(os.environ.get("USE_LAPACK")) or USE_OPENBLAS
USE_OPENMP = platform.system() != "Windows"
EIGEN_INCLUDE_DIR = os.environ.get("EIGEN_INCLUDE_DIR", "")
brownj85 marked this conversation as resolved.
Show resolved Hide resolved

config = {
"sources": ["./thewalrus/libwalrus.pyx"],
"depends": [
"./include/libwalrus.hpp",
"./include/eigenvalue_hafnian.hpp",
"./include/recursive_hafnian.hpp",
"./include/repeated_hafnian.hpp",
"./include/hafnian_approx.hpp",
"./include/torontonian.hpp",
"./include/permanent.hpp",
"./include/hermite_multidimensional.hpp",
"./include/stdafx.h",
"./include/fsum.hpp",
],
"extra_compile_args": [*{"-fPIC", "-std=c++11", *CFLAGS.split(" ")}],
"extra_link_args": [],
"include_dirs": ["./include", np.get_include()],
"language": "c++",
}

if platform.system() == "Windows":
config["extra_compile_args"].extend(("-static",))
config["extra_link_args"].extend(
("-static", "-static-libgfortran", "-static-libgcc")
)
elif platform.system() == "Darwin":
config["extra_compile_args"].extend(
("-Xpreprocessor", "-fopenmp", "-mmacosx-version-min=10.9", "-shared")
)
config["extra_link_args"].extend(("-Xpreprocessor", "-fopenmp", "-lomp"))
config["include_dirs"].append(
"/Applications/Xcode.app/Contents/Developer/Toolchains/"
"XcodeDefault.xctoolchain/usr/include/c++/v1/"
)
else:
config["extra_compile_args"].extend(("-fopenmp", "-shared"))
config["extra_link_args"].extend(("-fopenmp",))

if EIGEN_INCLUDE_DIR:
config["include_dirs"].append(EIGEN_INCLUDE_DIR)
else:
config["include_dirs"].extend(
("/usr/include/eigen3", "/usr/local/include/eigen3")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could define above

EIGEN_INCLUDE_DIR = ("/usr/include/eigen3", "/usr/local/include/eigen3", os.environ.get("EIGEN_INCLUDE_DIR")

to avoid the if statement here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the issue with this is that if Eigen is installed in the system and the user provides a custom path, there's no way to know which one the compiler will pick. The if statement ensures that the user-provided Eigen headers will always be used

)

if USE_OPENBLAS:
config["extra_compile_args"].append("-lopenblas")

if USE_LAPACK:
config["extra_compile_args"].extend(("-DLAPACKE=1", "-llapack"))

return cythonize(
[Extension("libwalrus", **config)],
compile_time_env={"_OPENMP": USE_OPENMP, "LAPACKE": USE_LAPACK},
)


def get_version():
with open("thewalrus/_version.py") as f:
return f.readlines()[-1].split()[-1].strip("\"'")


info = {
"name": "thewalrus",
"version": get_version(),
"maintainer": "Xanadu Inc.",
"maintainer_email": "nicolas@xanadu.ai",
"url": "https://github.com/XanaduAI/thewalrus",
"license": "Apache License 2.0",
"packages": find_packages(where="."),
"description": "Open source library for hafnian calculation",
"long_description": open("README.rst").read(),
"provides": ["thewalrus"],
"install_requires": [
"dask[delayed]",
"numba>=0.49.1",
"scipy>=1.2.1",
"sympy>=1.5.1",
"repoze.lru>=0.7",
],
"setup_requires": ["cython", "numpy"],
"ext_modules": build_extensions(),
"ext_package": "thewalrus",
}

classifiers = [
"Development Status :: 3 - Alpha",
"Environment :: Console",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: Apache Software License",
"Natural Language :: English",
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX :: Linux",
"Operating System :: Microsoft :: Windows",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Scientific/Engineering :: Physics",
]

setup(classifiers=classifiers, **(info))