fix undefined-behavior src/version.c:153:17
[liba.git] / setup.py
blobd1c012ab735fb4b220473cd0d50aa1d77155675e
1 #!/usr/bin/env python
2 from sys import argv
3 import os, sys
5 os.chdir(os.path.dirname(os.path.abspath(argv[0])))
6 if len(argv) < 2:
7 sys.argv += ["--quiet", "build_ext", "--inplace"]
8 try:
9 from setuptools.command.build_ext import build_ext
10 from setuptools import setup, Extension
11 except ImportError:
12 from distutils.command.build_ext import build_ext
13 from distutils.extension import Extension
14 from distutils.core import setup
15 LIBA_OPENMP = os.environ.get("LIBA_OPENMP")
16 if LIBA_OPENMP:
17 LIBA_OPENMP = int(LIBA_OPENMP)
18 LIBA_FLOAT = os.environ.get("LIBA_FLOAT")
19 if LIBA_FLOAT:
20 LIBA_FLOAT = int(LIBA_FLOAT)
21 else:
22 LIBA_FLOAT = 8
23 try:
24 USE_CYTHON = True
25 from sys import version_info
26 from Cython.Build import cythonize
27 except:
28 USE_CYTHON = False
29 from argparse import ArgumentParser
30 from sys import byteorder
31 from re import findall
32 import ctypes.util
33 import ctypes
36 def check_math(text=""):
37 if sys.platform == "win32":
38 path_libm = ctypes.util.find_library("ucrtbase")
39 if not path_libm:
40 path_libm = ctypes.util.find_msvcrt()
41 else:
42 path_libm = ctypes.util.find_library("m")
43 try:
44 libm = ctypes.CDLL(path_libm)
45 except:
46 return text
47 for func in (
48 "expm1",
49 "log1p",
50 "hypot",
51 "atan2",
52 "csqrt",
53 "cpow",
54 "cexp",
55 "clog",
56 "csin",
57 "ccos",
58 "ctan",
59 "csinh",
60 "ccosh",
61 "ctanh",
62 "casin",
63 "cacos",
64 "catan",
65 "casinh",
66 "cacosh",
67 "catanh",
69 name = "A_HAVE_" + func.upper()
70 if LIBA_FLOAT == 0x10:
71 func += "l"
72 if LIBA_FLOAT == 0x04:
73 func += "f"
74 try:
75 libm[func]
76 except:
77 continue
78 text += "#define %s 1\n" % (name)
79 return text
82 def configure(config):
83 with open("setup.cfg", "r") as f:
84 version = findall(r"version = (\S+)", f.read())[0]
85 major, minor, patch = findall(r"(\d+).(\d+).(\d+)", version)[0]
86 order = {"little": 1234, "big": 4321}.get(byteorder)
87 vsize = ctypes.sizeof(ctypes.c_void_p(0))
88 text = """/* autogenerated by setup.py */
89 #define A_VERSION "{}"
90 #define A_VERSION_MAJOR {}
91 #define A_VERSION_MINOR {}
92 #define A_VERSION_PATCH {}
93 #if !defined A_SIZE_POINTER
94 #define A_SIZE_POINTER {}
95 #endif /* A_SIZE_POINTER */
96 #if !defined A_BYTE_ORDER
97 #define A_BYTE_ORDER {}
98 #endif /* A_BYTE_ORDER */
99 {}""".format(
100 version, major, minor, patch, vsize, order, check_math()
102 with open(config, "wb") as f:
103 f.write(text.encode("UTF-8"))
106 parser = ArgumentParser(add_help=False)
107 parser.add_argument("-b", "--build-base", default="build")
108 parser.add_argument("-O", "--link-objects")
109 args = parser.parse_known_args(argv[1:])
110 base = args[0].build_base
112 sources, objects = [], []
113 config_h = os.path.join(base, "a.setup.h")
114 a_have_h = os.path.relpath(config_h, "include/a")
115 define_macros = [("A_HAVE_H", '"' + a_have_h + '"'), ("A_EXPORTS", None)]
116 if LIBA_FLOAT != 8:
117 define_macros += [("A_SIZE_FLOAT", LIBA_FLOAT)]
118 if USE_CYTHON and os.path.exists("python/src/a.pyx"):
119 sources += ["python/src/a.pyx"]
120 elif os.path.exists("python/src/a.c"):
121 sources += ["python/src/a.c"]
122 if not os.path.exists(base):
123 os.makedirs(base)
124 configure(config_h)
126 for dirpath, dirnames, filenames in os.walk("src"):
127 if args[0].link_objects:
128 break
129 for filename in filenames:
130 source = os.path.join(dirpath, filename)
131 if os.path.splitext(source)[-1] == ".c":
132 sources.append(source)
134 ext_modules = [
135 Extension(
136 name="liba",
137 language="c",
138 sources=sources,
139 include_dirs=["include"],
140 define_macros=define_macros,
143 if USE_CYTHON:
144 ext_modules = cythonize( # type: ignore
145 ext_modules,
146 language_level=version_info[0], # type: ignore
147 quiet=True,
151 class Build(build_ext): # type: ignore
152 def build_extensions(self):
153 if self.compiler.compiler_type == "msvc":
154 for e in self.extensions:
155 if LIBA_OPENMP:
156 e.extra_compile_args += ["/openmp"]
157 if not self.compiler.compiler_type == "msvc":
158 for e in self.extensions:
159 if LIBA_OPENMP:
160 e.extra_compile_args += ["-fopenmp"]
161 e.extra_link_args += ["-fopenmp"]
162 if self.compiler.compiler_type == "mingw32":
163 self.compiler.define_macro("__USE_MINGW_ANSI_STDIO", 1)
164 for e in self.extensions:
165 if e.language == "c++":
166 e.extra_link_args += ["-static-libstdc++"]
167 e.extra_link_args += ["-static-libgcc"]
168 e.extra_link_args += [
169 "-Wl,-Bstatic,--whole-archive",
170 "-lwinpthread",
171 "-Wl,--no-whole-archive",
173 build_ext.build_extensions(self)
176 setup(
177 ext_modules=ext_modules, # type: ignore
178 cmdclass={"build_ext": Build},