]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | from __future__ import print_function |
2 | ||
3 | import os | |
4 | import pkgutil | |
5 | import shutil | |
6 | import subprocess | |
7 | import sys | |
8 | import tempfile | |
9 | import textwrap | |
10 | from distutils.ccompiler import new_compiler | |
11 | from distutils.errors import CompileError, LinkError | |
9f95a23c | 12 | from itertools import filterfalse, takewhile |
11fdf7f2 TL |
13 | import distutils.sysconfig |
14 | ||
11fdf7f2 | 15 | |
9f95a23c TL |
16 | def filter_unsupported_flags(compiler, flags): |
17 | args = takewhile(lambda argv: not argv.startswith('-'), [compiler] + flags) | |
18 | if any('clang' in arg for arg in args): | |
19 | return list(filterfalse(lambda f: | |
20 | f in ('-mcet', | |
21 | '-fstack-clash-protection', | |
22 | '-fno-var-tracking-assignments', | |
23 | '-Wno-deprecated-register', | |
24 | '-Wno-gnu-designator') or | |
25 | f.startswith('-fcf-protection'), | |
26 | flags)) | |
11fdf7f2 TL |
27 | else: |
28 | return flags | |
29 | ||
11fdf7f2 | 30 | |
9f95a23c TL |
31 | def monkey_with_compiler(customize): |
32 | def patched(compiler): | |
33 | customize(compiler) | |
34 | if compiler.compiler_type != 'unix': | |
35 | return | |
36 | compiler.compiler[1:] = \ | |
37 | filter_unsupported_flags(compiler.compiler[0], | |
38 | compiler.compiler[1:]) | |
39 | compiler.compiler_so[1:] = \ | |
40 | filter_unsupported_flags(compiler.compiler_so[0], | |
41 | compiler.compiler_so[1:]) | |
42 | return patched | |
43 | ||
44 | ||
45 | distutils.sysconfig.customize_compiler = \ | |
46 | monkey_with_compiler(distutils.sysconfig.customize_compiler) | |
7c673cae FG |
47 | |
48 | if not pkgutil.find_loader('setuptools'): | |
49 | from distutils.core import setup | |
50 | from distutils.extension import Extension | |
51 | else: | |
52 | from setuptools import setup | |
53 | from setuptools.extension import Extension | |
54 | ||
55 | # PEP 440 versioning of the Ceph FS package on PyPI | |
56 | # Bump this version, after every changeset | |
57 | ||
58 | __version__ = '2.0.0' | |
59 | ||
60 | ||
9f95a23c TL |
61 | def get_python_flags(libs): |
62 | py_libs = sum((libs.split() for libs in | |
63 | distutils.sysconfig.get_config_vars('LIBS', 'SYSLIBS')), []) | |
64 | compiler = new_compiler() | |
65 | distutils.sysconfig.customize_compiler(compiler) | |
66 | return dict( | |
67 | include_dirs=[distutils.sysconfig.get_python_inc()], | |
68 | library_dirs=distutils.sysconfig.get_config_vars('LIBDIR', 'LIBPL'), | |
69 | libraries=libs + [lib.replace('-l', '') for lib in py_libs], | |
70 | extra_compile_args=filter_unsupported_flags( | |
71 | compiler.compiler[0], | |
72 | distutils.sysconfig.get_config_var('CFLAGS').split()), | |
73 | extra_link_args=(distutils.sysconfig.get_config_var('LDFLAGS').split() + | |
74 | distutils.sysconfig.get_config_var('LINKFORSHARED').split())) | |
7c673cae FG |
75 | |
76 | ||
77 | def check_sanity(): | |
78 | """ | |
79 | Test if development headers and library for cephfs is available by compiling a dummy C program. | |
80 | """ | |
81 | CEPH_SRC_DIR = os.path.join( | |
82 | os.path.dirname(os.path.abspath(__file__)), | |
83 | '..', | |
84 | '..' | |
85 | ) | |
86 | ||
87 | tmp_dir = tempfile.mkdtemp(dir=os.environ.get('TMPDIR', os.path.dirname(__file__))) | |
88 | tmp_file = os.path.join(tmp_dir, 'cephfs_dummy.c') | |
89 | ||
90 | with open(tmp_file, 'w') as fp: | |
91 | dummy_prog = textwrap.dedent(""" | |
92 | #include <stddef.h> | |
93 | #include "cephfs/libcephfs.h" | |
94 | ||
95 | int main(void) { | |
96 | struct ceph_mount_info *cmount = NULL; | |
97 | ceph_init(cmount); | |
98 | return 0; | |
99 | } | |
100 | """) | |
101 | fp.write(dummy_prog) | |
102 | ||
103 | compiler = new_compiler() | |
11fdf7f2 | 104 | distutils.sysconfig.customize_compiler(compiler) |
7c673cae | 105 | |
9f95a23c | 106 | if 'CEPH_LIBDIR' in os.environ: |
7c673cae FG |
107 | # The setup.py has been invoked by a top-level Ceph make. |
108 | # Set the appropriate CFLAGS and LDFLAGS | |
7c673cae FG |
109 | compiler.set_library_dirs([os.environ.get('CEPH_LIBDIR')]) |
110 | ||
111 | try: | |
112 | compiler.define_macro('_FILE_OFFSET_BITS', '64') | |
113 | ||
114 | link_objects = compiler.compile( | |
115 | sources=[tmp_file], | |
116 | output_dir=tmp_dir, | |
117 | extra_preargs=['-iquote{path}'.format(path=os.path.join(CEPH_SRC_DIR, 'include'))] | |
118 | ) | |
119 | ||
120 | compiler.link_executable( | |
121 | objects=link_objects, | |
122 | output_progname=os.path.join(tmp_dir, 'cephfs_dummy'), | |
123 | libraries=['cephfs'], | |
124 | output_dir=tmp_dir, | |
125 | ) | |
126 | ||
127 | except CompileError: | |
128 | print('\nCompile Error: Ceph FS development headers not found', file=sys.stderr) | |
129 | return False | |
130 | except LinkError: | |
131 | print('\nLink Error: Ceph FS library not found', file=sys.stderr) | |
132 | return False | |
133 | else: | |
134 | return True | |
135 | finally: | |
136 | shutil.rmtree(tmp_dir) | |
137 | ||
138 | ||
139 | if 'BUILD_DOC' in os.environ.keys(): | |
140 | pass | |
141 | elif check_sanity(): | |
142 | pass | |
143 | else: | |
144 | sys.exit(1) | |
145 | ||
146 | cmdclass = {} | |
147 | try: | |
148 | from Cython.Build import cythonize | |
149 | from Cython.Distutils import build_ext | |
150 | ||
151 | cmdclass = {'build_ext': build_ext} | |
152 | except ImportError: | |
153 | print("WARNING: Cython is not installed.") | |
154 | ||
155 | if not os.path.isfile('cephfs.c'): | |
156 | print('ERROR: Cannot find Cythonized file cephfs.c', file=sys.stderr) | |
157 | sys.exit(1) | |
158 | else: | |
159 | def cythonize(x, **kwargs): | |
160 | return x | |
161 | ||
162 | source = "cephfs.c" | |
163 | else: | |
164 | source = "cephfs.pyx" | |
165 | ||
166 | # Disable cythonification if we're not really building anything | |
167 | if (len(sys.argv) >= 2 and | |
168 | any(i in sys.argv[1:] for i in ('--help', 'clean', 'egg_info', '--version') | |
169 | )): | |
170 | def cythonize(x, **kwargs): | |
171 | return x | |
172 | ||
7c673cae FG |
173 | setup( |
174 | name='cephfs', | |
175 | version=__version__, | |
176 | description="Python bindings for the Ceph FS library", | |
177 | long_description=( | |
178 | "This package contains Python bindings for interacting with the " | |
179 | "Ceph Filesystem (Ceph FS) library. Ceph FS is a POSIX-compliant " | |
180 | "filesystem that uses a Ceph Storage Cluster to store its data. The " | |
181 | "Ceph filesystem uses the same Ceph Storage Cluster system as " | |
182 | "Ceph Block Devices, Ceph Object Storage with its S3 and Swift APIs, " | |
183 | "or native bindings (librados)." | |
184 | ), | |
185 | url='https://github.com/ceph/ceph/tree/master/src/pybind/cephfs', | |
186 | license='LGPLv2+', | |
187 | platforms='Linux', | |
188 | ext_modules=cythonize( | |
189 | [ | |
190 | Extension( | |
191 | "cephfs", | |
192 | [source], | |
9f95a23c | 193 | **get_python_flags(['cephfs']) |
7c673cae FG |
194 | ) |
195 | ], | |
9f95a23c | 196 | compiler_directives={'language_level': sys.version_info.major}, |
7c673cae FG |
197 | build_dir=os.environ.get("CYTHON_BUILD_DIR", None), |
198 | include_path=[ | |
199 | os.path.join(os.path.dirname(__file__), "..", "rados") | |
200 | ] | |
201 | ), | |
202 | classifiers=[ | |
203 | 'Intended Audience :: Developers', | |
204 | 'Intended Audience :: System Administrators', | |
205 | 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)', | |
206 | 'Operating System :: POSIX :: Linux', | |
207 | 'Programming Language :: Cython', | |
208 | 'Programming Language :: Python :: 2.7', | |
209 | 'Programming Language :: Python :: 3.4', | |
210 | 'Programming Language :: Python :: 3.5' | |
211 | ], | |
212 | cmdclass=cmdclass, | |
213 | ) |