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