515590fb01468a1d9218705d8644e661487f205d
[obnox/samba/samba-obnox.git] / buildtools / wafsamba / samba_bundled.py
1 # functions to support bundled libraries
2
3 from Configure import conf
4 import sys, Logs
5 from samba_utils import *
6
7 def PRIVATE_NAME(bld, name, private_extension, private_library):
8     '''possibly rename a library to include a bundled extension'''
9
10     if not private_library:
11         return name
12
13     # we now use the same private name for libraries as the public name.
14     # see http://git.samba.org/?p=tridge/junkcode.git;a=tree;f=shlib for a
15     # demonstration that this is the right thing to do
16     # also see http://lists.samba.org/archive/samba-technical/2011-January/075816.html
17     if private_extension:
18         return name
19
20     extension = bld.env.PRIVATE_EXTENSION
21
22     if extension and name.startswith('%s' % extension):
23         return name
24
25     if extension and name.endswith('%s' % extension):
26         return name
27
28     return "%s-%s" % (name, extension)
29
30
31 def target_in_list(target, lst, default):
32     for l in lst:
33         if target == l:
34             return True
35         if '!' + target == l:
36             return False
37         if l == 'ALL':
38             return True
39         if l == 'NONE':
40             return False
41     return default
42
43
44 def BUILTIN_LIBRARY(bld, name):
45     '''return True if a library should be builtin
46        instead of being built as a shared lib'''
47     return target_in_list(name, bld.env.BUILTIN_LIBRARIES, False)
48 Build.BuildContext.BUILTIN_LIBRARY = BUILTIN_LIBRARY
49
50
51 def BUILTIN_DEFAULT(opt, builtins):
52     '''set a comma separated default list of builtin libraries for this package'''
53     if 'BUILTIN_LIBRARIES_DEFAULT' in Options.options:
54         return
55     Options.options['BUILTIN_LIBRARIES_DEFAULT'] = builtins
56 Options.Handler.BUILTIN_DEFAULT = BUILTIN_DEFAULT
57
58
59 def PRIVATE_EXTENSION_DEFAULT(opt, extension, noextension=''):
60     '''set a default private library extension'''
61     if 'PRIVATE_EXTENSION_DEFAULT' in Options.options:
62         return
63     Options.options['PRIVATE_EXTENSION_DEFAULT'] = extension
64     Options.options['PRIVATE_EXTENSION_EXCEPTION'] = noextension
65 Options.Handler.PRIVATE_EXTENSION_DEFAULT = PRIVATE_EXTENSION_DEFAULT
66
67
68 def minimum_library_version(conf, libname, default):
69     '''allow override of mininum system library version'''
70
71     minlist = Options.options.MINIMUM_LIBRARY_VERSION
72     if not minlist:
73         return default
74
75     for m in minlist.split(','):
76         a = m.split(':')
77         if len(a) != 2:
78             Logs.error("Bad syntax for --minimum-library-version of %s" % m)
79             sys.exit(1)
80         if a[0] == libname:
81             return a[1]
82     return default
83
84
85 @conf
86 def LIB_MAY_BE_BUNDLED(conf, libname):
87     if libname in conf.env.BUNDLED_LIBS:
88         return True
89     if '!%s' % libname in conf.env.BUNDLED_LIBS:
90         return False
91     if 'NONE' in conf.env.BUNDLED_LIBS:
92         return False
93     return True
94
95 @conf
96 def LIB_MUST_BE_BUNDLED(conf, libname):
97     if libname in conf.env.BUNDLED_LIBS:
98         return True
99     if '!%s' % libname in conf.env.BUNDLED_LIBS:
100         return False
101     if 'ALL' in conf.env.BUNDLED_LIBS:
102         return True
103     return False
104
105 @conf
106 def LIB_MUST_BE_PRIVATE(conf, libname):
107     return ('ALL' in conf.env.PRIVATE_LIBS or
108             libname in conf.env.PRIVATE_LIBS)
109
110 @conf
111 def CHECK_PREREQUISITES(conf, prereqs):
112     missing = []
113     for syslib in TO_LIST(prereqs):
114         f = 'FOUND_SYSTEMLIB_%s' % syslib
115         if not f in conf.env:
116             missing.append(syslib)
117     return missing
118
119
120 @runonce
121 @conf
122 def CHECK_BUNDLED_SYSTEM_PKG(conf, libname, minversion='0.0.0',
123         onlyif=None, implied_deps=None, pkg=None):
124     '''check if a library is available as a system library.
125
126     This only tries using pkg-config
127     '''
128     return conf.CHECK_BUNDLED_SYSTEM(libname,
129                                      minversion=minversion,
130                                      onlyif=onlyif,
131                                      implied_deps=implied_deps,
132                                      pkg=pkg)
133
134 @runonce
135 @conf
136 def CHECK_BUNDLED_SYSTEM(conf, libname, minversion='0.0.0',
137                          checkfunctions=None, headers=None, checkcode=None,
138                          onlyif=None, implied_deps=None,
139                          require_headers=True, pkg=None, set_target=True):
140     '''check if a library is available as a system library.
141     this first tries via pkg-config, then if that fails
142     tries by testing for a specified function in the specified lib
143     '''
144     if conf.LIB_MUST_BE_BUNDLED(libname):
145         return False
146     found = 'FOUND_SYSTEMLIB_%s' % libname
147     if found in conf.env:
148         return conf.env[found]
149
150     def check_functions_headers_code():
151         '''helper function for CHECK_BUNDLED_SYSTEM'''
152         if require_headers and headers and not conf.CHECK_HEADERS(headers, lib=libname):
153             return False
154         if checkfunctions is not None:
155             ok = conf.CHECK_FUNCS_IN(checkfunctions, libname, headers=headers,
156                                      empty_decl=False, set_target=False)
157             if not ok:
158                 return False
159         if checkcode is not None:
160             define='CHECK_BUNDLED_SYSTEM_%s' % libname.upper()
161             ok = conf.CHECK_CODE(checkcode, lib=libname,
162                                  headers=headers, local_include=False,
163                                  msg=msg, define=define)
164             conf.CONFIG_RESET(define)
165             if not ok:
166                 return False
167         return True
168
169
170     # see if the library should only use a system version if another dependent
171     # system version is found. That prevents possible use of mixed library
172     # versions
173     if onlyif:
174         missing = conf.CHECK_PREREQUISITES(onlyif)
175         if missing:
176             if not conf.LIB_MAY_BE_BUNDLED(libname):
177                 Logs.error('ERROR: Use of system library %s depends on missing system library/libraries %r' % (libname, missing))
178                 sys.exit(1)
179             conf.env[found] = False
180             return False
181
182     minversion = minimum_library_version(conf, libname, minversion)
183
184     msg = 'Checking for system %s' % libname
185     if minversion != '0.0.0':
186         msg += ' >= %s' % minversion
187
188     uselib_store=libname.upper()
189     if pkg is None:
190         pkg = libname
191
192     # try pkgconfig first
193     if (conf.check_cfg(package=pkg,
194                       args='"%s >= %s" --cflags --libs' % (pkg, minversion),
195                       msg=msg, uselib_store=uselib_store) and
196         check_functions_headers_code()):
197         if set_target:
198             conf.SET_TARGET_TYPE(libname, 'SYSLIB')
199         conf.env[found] = True
200         if implied_deps:
201             conf.SET_SYSLIB_DEPS(libname, implied_deps)
202         return True
203     if checkfunctions is not None:
204         if check_functions_headers_code():
205             conf.env[found] = True
206             if implied_deps:
207                 conf.SET_SYSLIB_DEPS(libname, implied_deps)
208             if set_target:
209                 conf.SET_TARGET_TYPE(libname, 'SYSLIB')
210             return True
211     conf.env[found] = False
212     if not conf.LIB_MAY_BE_BUNDLED(libname):
213         Logs.error('ERROR: System library %s of version %s not found, and bundling disabled' % (libname, minversion))
214         sys.exit(1)
215     return False
216
217
218 def tuplize_version(version):
219     return tuple([int(x) for x in version.split(".")])
220
221 @runonce
222 @conf
223 def CHECK_BUNDLED_SYSTEM_PYTHON(conf, libname, modulename, minversion='0.0.0'):
224     '''check if a python module is available on the system and
225     has the specified minimum version.
226     '''
227     if conf.LIB_MUST_BE_BUNDLED(libname):
228         return False
229
230     # see if the library should only use a system version if another dependent
231     # system version is found. That prevents possible use of mixed library
232     # versions
233     minversion = minimum_library_version(conf, libname, minversion)
234
235     try:
236         m = __import__(modulename)
237     except ImportError:
238         found = False
239     else:
240         try:
241             version = m.__version__
242         except AttributeError:
243             found = False
244         else:
245             found = tuplize_version(version) >= tuplize_version(minversion)
246     if not found and not conf.LIB_MAY_BE_BUNDLED(libname):
247         Logs.error('ERROR: Python module %s of version %s not found, and bundling disabled' % (libname, minversion))
248         sys.exit(1)
249     return found
250
251
252 def NONSHARED_BINARY(bld, name):
253     '''return True if a binary should be built without non-system shared libs'''
254     return target_in_list(name, bld.env.NONSHARED_BINARIES, False)
255 Build.BuildContext.NONSHARED_BINARY = NONSHARED_BINARY
256
257