Skip to content

Commit a2a20f1

Browse files
committed
more robust setup.py
1 parent da768f8 commit a2a20f1

3 files changed

Lines changed: 101 additions & 27 deletions

File tree

pygalmesh/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
)
2323

2424
from . import _cli
25-
from .__about__ import __version__, __cgal_version__
25+
from .__about__ import __cgal_version__, __version__
2626
from .main import (
2727
generate_2d,
2828
generate_from_array,

setup.cfg

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ keywords =
3131
3232
[options]
3333
packages = find:
34-
setup_requires = pybind11 >= 2.2
34+
setup_requires = pybind11 >= 2.5
3535
install_requires =
3636
importlib_metadata;python_version<"3.8"
3737
meshio >= 4.0.0, < 5.0.0
3838
numpy
39-
pybind11 >= 2.2
39+
pybind11 >= 2.5
4040
python_requires = >=3.6
4141
4242
[options.entry_points]

setup.py

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,126 @@
11
import os
2+
import sys
23

4+
import setuptools
35
from setuptools import Extension, setup
6+
from setuptools.command.build_ext import build_ext
47

58

6-
class get_pybind_include:
7-
"""Helper class to determine the pybind11 include path. The purpose of this class is
8-
to postpone importing pybind11 until it is actually installed, so that the
9-
``get_include()`` method can be invoked.
10-
"""
11-
12-
def __init__(self, user=False):
13-
self.user = user
9+
# <https://github.com/pybind/python_example/blob/master/setup.py>
10+
class get_pybind_include(object):
11+
"""Helper class to determine the pybind11 include path
12+
The purpose of this class is to postpone importing pybind11
13+
until it is actually installed, so that the ``get_include()``
14+
method can be invoked."""
1415

1516
def __str__(self):
1617
import pybind11
1718

18-
return pybind11.get_include(self.user)
19+
return pybind11.get_include()
20+
21+
22+
# cf http://bugs.python.org/issue26689
23+
def has_flag(compiler, flagname):
24+
"""Return a boolean indicating whether a flag name is supported on
25+
the specified compiler.
26+
"""
27+
import os
28+
import tempfile
29+
30+
with tempfile.NamedTemporaryFile("w", suffix=".cpp", delete=False) as f:
31+
f.write("int main (int argc, char **argv) { return 0; }")
32+
fname = f.name
33+
try:
34+
compiler.compile([fname], extra_postargs=[flagname])
35+
except setuptools.distutils.errors.CompileError:
36+
return False
37+
finally:
38+
try:
39+
os.remove(fname)
40+
except OSError:
41+
pass
42+
return True
43+
44+
45+
def cpp_flag(compiler):
46+
"""Return the -std=c++[11/14/17] compiler flag.
47+
The newer version is prefered over c++11 (when it is available).
48+
"""
49+
flags = ["-std=c++17", "-std=c++14", "-std=c++11"]
50+
51+
for flag in flags:
52+
if has_flag(compiler, flag):
53+
return flag
54+
55+
raise RuntimeError("Unsupported compiler -- at least C++11 support " "is needed!")
56+
57+
58+
class BuildExt(build_ext):
59+
"""A custom build extension for adding compiler-specific options."""
60+
61+
c_opts = {
62+
"msvc": ["/EHsc"],
63+
"unix": [],
64+
}
65+
l_opts = {
66+
"msvc": [],
67+
"unix": [],
68+
}
69+
70+
if sys.platform == "darwin":
71+
darwin_opts = ["-stdlib=libc++", "-mmacosx-version-min=10.7"]
72+
c_opts["unix"] += darwin_opts
73+
l_opts["unix"] += darwin_opts
74+
75+
def build_extensions(self):
76+
ct = self.compiler.compiler_type
77+
opts = self.c_opts.get(ct, [])
78+
link_opts = self.l_opts.get(ct, [])
79+
if ct == "unix":
80+
opts.append(cpp_flag(self.compiler))
81+
if has_flag(self.compiler, "-fvisibility=hidden"):
82+
opts.append("-fvisibility=hidden")
83+
84+
for ext in self.extensions:
85+
ext.define_macros = [
86+
("VERSION_INFO", '"{}"'.format(self.distribution.get_version()))
87+
]
88+
ext.extra_compile_args = opts
89+
ext.extra_link_args = link_opts
90+
build_ext.build_extensions(self)
1991

2092

2193
ext_modules = [
2294
Extension(
2395
"_pygalmesh",
24-
[
25-
"src/generate.cpp",
26-
"src/generate_2d.cpp",
27-
"src/generate_from_inr.cpp",
28-
"src/generate_from_off.cpp",
29-
"src/generate_periodic.cpp",
30-
"src/generate_surface_mesh.cpp",
31-
"src/remesh_surface.cpp",
32-
"src/version.cpp",
33-
"src/pybind11.cpp",
34-
],
35-
language="c++",
96+
# Sort input source files to ensure bit-for-bit reproducible builds
97+
# (https://github.com/pybind/python_example/pull/53)
98+
sorted(
99+
[
100+
"src/generate.cpp",
101+
"src/generate_2d.cpp",
102+
"src/generate_from_inr.cpp",
103+
"src/generate_from_off.cpp",
104+
"src/generate_periodic.cpp",
105+
"src/generate_surface_mesh.cpp",
106+
"src/remesh_surface.cpp",
107+
"src/pybind11.cpp",
108+
]
109+
),
36110
include_dirs=[
37111
os.environ.get("EIGEN_INCLUDE_DIR", "/usr/include/eigen3/"),
38112
# Path to pybind11 headers
39113
get_pybind_include(),
40-
get_pybind_include(user=True),
41114
],
42-
extra_compile_args=["-std=c++14"],
115+
language="c++",
43116
# no CGAL libraries necessary from CGAL 5.0 onwards
44117
libraries=["gmp", "mpfr"],
45118
)
46119
]
47120

48121
if __name__ == "__main__":
49122
setup(
50-
# cmdclass={'build_ext': BuildExt},
123+
cmdclass={"build_ext": BuildExt},
51124
ext_modules=ext_modules,
125+
zip_safe=False,
52126
)

0 commit comments

Comments
 (0)