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