Ignore *.exe
[awesomized/libmemcached] / config / pandora-plugin
1 #!/usr/bin/python
2
3 # Copyright (C) 2009 Sun Microsystems
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; version 2 of the License.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18 pandora_plugin_file = 'config/pandora-plugin.ini'
19
20 # Find plugins in the tree and add them to the build system
21
22 import ConfigParser, os, sys
23 import datetime, time
24 import subprocess
25
26 plugin_am_file=None
27 plugin_ac_file=None
28
29 class ChangeProtectedFile(object):
30
31 def __init__(self, fname):
32 self.bogus_file= False
33 self.real_fname= fname
34 self.new_fname= "%s.new" % fname
35 try:
36 self.new_file= open(self.new_fname,'w+')
37 except IOError:
38 self.bogus_file= True
39
40 def write(self, text):
41 if not self.bogus_file:
42 self.new_file.write(text)
43
44 # We've written all of this out into .new files, now we only copy them
45 # over the old ones if they are different, so that we don't cause
46 # unnecessary recompiles
47 def close(self):
48 """Return True if the file had changed."""
49 if self.bogus_file:
50 return
51 self.new_file.seek(0)
52 new_content = self.new_file.read()
53 self.new_file.close()
54 try:
55 old_file = file(self.real_fname, 'r')
56 old_content = old_file.read()
57 old_file.close()
58 except IOError:
59 old_content = None
60 if new_content != old_content:
61 if old_content != None:
62 os.unlink(self.real_fname)
63 os.rename(self.new_fname, self.real_fname)
64 return True
65 else:
66 try:
67 os.unlink(self.new_fname)
68 except:
69 pass
70
71
72 def write_external_configure(plugin, plugin_file):
73 """Write the initial bits of the configure.ac file"""
74 if not os.path.exists('m4'):
75 os.mkdir('m4')
76 plugin_file.write("""
77 AC_PREREQ(2.59)dnl Minimum Autoconf version required.
78 AC_INIT([%(name)s],[%(version)s],[%(url)s])
79 AC_CONFIG_SRCDIR([%(main_source)s])
80 AC_CONFIG_AUX_DIR(config)
81
82 PANDORA_CANONICAL_TARGET(less-warnings, warnings-always-on, require-cxx, force-gcc42,skip-visibility)
83
84 PANDORA_REQUIRE_LIBPROTOBUF
85 PANDORA_PROTOBUF_REQUIRE_VERSION([2.1.0])
86 PANDORA_REQUIRE_PROTOC
87
88 AC_LANG_PUSH(C++)
89 PANDORA_REQUIRE_PTHREAD
90 PANDORA_REQUIRE_LIBDL
91 AC_LANG_POP
92
93 PANDORA_USE_BETTER_MALLOC
94
95 PANDORA_DRIZZLE_BUILD
96 """ % plugin)
97
98 write_plugin_ac(plugin, plugin_file)
99
100 plugin_file.write("""
101 AC_CONFIG_FILES(Makefile)
102
103 AC_OUTPUT
104
105 echo "---"
106 echo "Configuration summary for $PACKAGE_NAME version $VERSION $PANDORA_RELEASE_COMMENT"
107 echo ""
108 echo " * Installation prefix: $prefix"
109 echo " * System type: $host_vendor-$host_os"
110 echo " * Host CPU: $host_cpu"
111 echo " * C Compiler: $CC_VERSION"
112 echo " * C++ Compiler: $CXX_VERSION"
113 echo " * Debug enabled: $with_debug"
114 echo " * Warnings as failure: $ac_cv_warnings_as_errors"
115 echo " * C++ cstdint location: $ac_cv_cxx_cstdint"
116 echo " * C++ hash_map location: $ac_cv_cxx_hash_map"
117 echo " * C++ hash namespace: $ac_cv_cxx_hash_namespace"
118 echo " * C++ shared_ptr namespace: $ac_cv_shared_ptr_namespace"
119 echo ""
120 echo "---"
121
122 """ % plugin)
123
124 def write_external_makefile(plugin, plugin_file):
125
126 plugin_file.write("""
127 ACLOCAL_AMFLAGS = -I m4 --force
128 VERSION=$(PANDORA_RELEASE_VERSION)
129
130 pkgplugindir=%(pkgplugindir)s
131 EXTRA_DIST = plugin.ini
132
133 """ % plugin)
134 if plugin['headers'] != "":
135 plugin_file.write("noinst_HEADERS = %(headers)s\n" % plugin)
136 if plugin['install_headers'] != "":
137 plugin_file.write("nobase_include_HEADERS += %(install_headers)s\n" % plugin)
138 if plugin['testsuite']:
139 if plugin.has_key('testsuitedir') and plugin['testsuitedir'] != "":
140 plugin_file.write("EXTRA_DIST += %(testsuitedir)s\n" % plugin)
141 plugin_file.write("""
142 pkgplugin_LTLIBRARIES=%(libname)s.la
143 %(libname)s_la_LDFLAGS=-avoid-version -rpath $(pkgplugindir) $(AM_LDFLAGS) %(ldflags)s $(GCOV_LIBS)
144 %(libname)s_la_LIBADD=%(libs)s
145 %(libname)s_la_DEPENDENCIES=%(libs)s
146 %(libname)s_la_CPPFLAGS=$(AM_CPPFLAGS) -DPANDORA_DYNAMIC_PLUGIN -DPANDORA_MODULE_NAME=%(module_name)s -DPANDORA_MODULE_AUTHOR='"%(author)s"' -DPANDORA_MODULE_TITLE='"%(title)s"' -DPANDORA_MODULE_VERSION='"%(version)s"' -DPANDORA_MODULE_LICENSE=%(license)s %(cppflags)s
147 %(libname)s_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
148 %(libname)s_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
149 %(libname)s_la_SOURCES=%(sources)s
150 check_PROGRAMS += %(tests)s
151 """ % plugin)
152 plugin_am_file=os.path.join(plugin['rel_path'],'plugin.am')
153 if os.path.exists(plugin_am_file):
154 plugin_file.write('include %s\n' % plugin_am_file)
155
156 def write_external_plugin():
157 """Return True if the plugin had changed."""
158 plugin = read_plugin_ini('.')
159 expand_plugin_ini(plugin)
160 plugin_file = ChangeProtectedFile('configure.ac')
161 write_external_configure(plugin, plugin_file)
162 result = plugin_file.close()
163 plugin_file = ChangeProtectedFile('Makefile.am')
164 write_external_makefile(plugin, plugin_file)
165 # Write some stub configure.ac and Makefile.am files that include the above
166 result = plugin_file.close() or result
167 return result
168
169 def write_plugin(plugin, plugin_ini_list):
170 # Since this function is recursive, make sure we're not already in it.
171 if plugin.has_key('writing_status'):
172 if plugin['writing_status'] == 'done':
173 return
174 else:
175 print "Dependency loop detected with %s" % plugin['name']
176 exit(1)
177
178 plugin['writing_status'] = 'dependencies'
179
180 # Write all dependencies first to get around annoying automake bug
181 for dependency in plugin['dependency_list']:
182 found = False
183 for find_plugin in plugin_ini_list:
184 if find_plugin['module_name'] == dependency:
185 found = True
186 write_plugin(find_plugin, plugin_ini_list)
187 break
188 if found is False:
189 print "Could not find dependency %s: %s" % (plugin['name'], dependency)
190 exit(1)
191
192 write_plugin_ac(plugin, plugin_ac_file)
193 write_plugin_am(plugin, plugin_am_file)
194 plugin['writing_status'] = 'done'
195
196 def write_plugin_ac(plugin, plugin_ac):
197 #
198 # Write plugin config instructions into plugin.ac file.
199 #
200 plugin_ac_file=os.path.join(plugin['rel_path'],'plugin.ac')
201 plugin_m4_dir=os.path.join(plugin['rel_path'],'m4')
202 plugin_m4_files=[]
203 if os.path.exists(plugin_m4_dir) and os.path.isdir(plugin_m4_dir):
204 for m4_file in os.listdir(plugin_m4_dir):
205 if os.path.splitext(m4_file)[-1] == '.m4':
206 plugin_m4_files.append(os.path.join(plugin['rel_path'], m4_file))
207 plugin_ac.write("""
208 dnl Config for %(title)s
209 """ % plugin)
210 for m4_file in plugin_m4_files:
211 plugin_ac.write('m4_sinclude([%s])\n' % m4_file)
212 plugin['plugin_dep_libs']=" ".join(["\${top_builddir}/%s" % f for f in plugin['libs'].split()])
213
214 plugin_ac.write("""
215 AC_ARG_WITH([%(name_with_dashes)s-plugin],[
216 dnl indented wierd to make the help output correct
217 AS_HELP_STRING([--with-%(name_with_dashes)s-plugin],[Build %(title)s. @<:@default=%(enabled)s@:>@])
218 AS_HELP_STRING([--without-%(name_with_dashes)s-plugin],[Disable building %(title)s])
219 ],[
220 with_%(name)s_plugin="$withval"
221 AS_IF([test "x$with_%(name)s_plugin" = "xyes"],[
222 requested_%(name)s_plugin="yes"
223 ],[
224 requested_%(name)s_plugin="no"
225 ])
226 ],[
227 with_%(name)s_plugin="%(enabled)s"
228 requested_%(name)s_plugin="no"
229 ])
230 AC_ARG_ENABLE([%(name_with_dashes)s-plugin],[
231 dnl indented wierd to make the help output correct
232 AS_HELP_STRING([--enable-%(name_with_dashes)s-plugin],[Build %(title)s. @<:@default=%(default_yesno)s@:>@])
233 AS_HELP_STRING([--disable-%(name_with_dashes)s-plugin],[Disable building %(title)s])
234 ],
235 [enable_%(name)s_plugin="$enableval"],
236 [enable_%(name)s_plugin=%(default_yesno)s])
237
238 """ % plugin)
239 if os.path.exists(plugin_ac_file):
240 plugin_ac.write('m4_sinclude([%s])\n' % plugin_ac_file)
241 # The plugin author has specified some check to make to determine
242 # if the plugin can be built. If the plugin is turned on and this
243 # check fails, then configure should error out. If the plugin is not
244 # turned on, then the normal conditional build stuff should just let
245 # it silently not build
246 if plugin['has_build_conditional']:
247 plugin_ac.write("""
248 AS_IF([test %(build_conditional)s],
249 [], dnl build_conditional can only negate
250 [
251 AS_IF([test "x${requested_%(name)s_plugin}" = "xyes"],
252 [AC_MSG_ERROR([Plugin %(name)s was explicitly requested, yet failed build dependency checks. Aborting!])])
253 with_%(name)s_plugin=no
254 ])
255
256 """ % plugin)
257 if not plugin['unconditional']:
258 plugin_ac.write("""
259 AM_CONDITIONAL([%(build_conditional_tag)s],
260 [test %(build_conditional)s])
261 """ % plugin)
262
263 plugin_ac.write("""
264 AS_IF([test "x$with_%(name)s_plugin" = "xyes"],
265 [
266 """ % plugin)
267 if plugin['testsuite']:
268 plugin_ac.write("""
269 pandora_plugin_test_list="%(name)s,${pandora_plugin_test_list}"
270 """ % plugin)
271 if plugin['static']:
272 plugin_ac.write("""
273 AS_IF([test "x$enable_%(name)s_plugin" = "xyes"],[
274 pandora_builtin_list="%(module_name)s,${pandora_builtin_list}"
275 pandora_builtin_symbols_list="_drizzled_%(module_name)s_plugin_,${pandora_builtin_symbols_list}"
276 pandora_plugin_libs="${pandora_plugin_libs} \${top_builddir}/%(root_plugin_dir)s/%(libname)s.la"
277 PANDORA_PLUGIN_DEP_LIBS="${PANDORA_PLUGIN_DEP_LIBS} %(plugin_dep_libs)s"
278 ])
279 """ % plugin)
280
281 else:
282 plugin_ac.write("""
283 AS_IF([test "x$enable_%(name)s_plugin" = "xyes"],[
284 pandora_default_plugin_list="%(name)s,${pandora_default_plugin_list}"
285 ])
286 """ % plugin)
287 plugin_ac.write(" ])\n")
288
289 def fix_file_paths(plugin, files):
290 # TODO: determine path to plugin dir relative to top_srcdir... append it to
291 # source files if they don't already have it
292 new_files=""
293 if plugin['plugin_dir'] != ".":
294 for file in files.split():
295 if not file.startswith(plugin['rel_path']):
296 file= os.path.join(plugin['rel_path'], file)
297 new_files= "%s %s" % (new_files, file)
298 else:
299 new_files= " ".join(plugin['sources'].split())
300 if new_files != "":
301 return new_files
302 return files
303
304 def expand_plugin_ini(plugin):
305 if plugin['name'] == "**OUT-OF-TREE**":
306 print "Out of tree plugins require the name field to be specified in plugin.ini"
307 sys.exit(1)
308
309 if plugin['plugin_dir'] == ".":
310 plugin['rel_path']= plugin['plugin_dir']
311 plugin['unconditional']=True
312 else:
313 plugin['rel_path']= plugin['plugin_dir'][len(config['top_srcdir'])+len(os.path.sep):]
314 plugin['unconditional']=False
315
316 plugin['sources']= fix_file_paths(plugin, plugin['sources'])
317 plugin['main_source']= plugin['sources'].split()[0]
318 plugin['headers']= fix_file_paths(plugin, plugin['headers'])
319 plugin['install_headers']= fix_file_paths(plugin, plugin['install_headers'])
320 plugin['tests']= fix_file_paths(plugin, plugin['tests'])
321
322 # Make a yes/no version for autoconf help messages
323 if plugin['load_by_default'] or plugin['static']:
324 plugin['default_yesno']="yes"
325 else:
326 plugin['default_yesno']="no"
327
328
329 plugin['build_conditional_tag']= "BUILD_%s_PLUGIN" % plugin['name'].upper()
330 plugin['name_with_dashes']= plugin['name'].replace('_','-')
331 if plugin.has_key('build_conditional'):
332 plugin['has_build_conditional']=True
333 plugin['build_conditional']='"x${with_%(name)s_plugin}" = "xyes" -a %(build_conditional)s' % plugin
334 else:
335 plugin['has_build_conditional']=False
336 plugin['build_conditional']='"x${with_%(name)s_plugin}" = "xyes"' %plugin
337
338 if plugin['install']:
339 plugin['library_type']= 'pkgplugin'
340 else:
341 plugin['library_type']= 'noinst'
342
343 def find_testsuite(plugin_dir):
344 for testdir in ['drizzle-tests','tests']:
345 if os.path.isdir(os.path.join(plugin_dir,testdir)):
346 return testdir
347 if os.path.isdir(os.path.join('tests','suite',os.path.basename(plugin_dir))):
348 return ""
349 return None
350
351 def read_plugin_ini(plugin_dir):
352 if plugin_dir == ".":
353 plugin_name="**OUT-OF-TREE**"
354 else:
355 short_name=os.path.basename(plugin_dir)
356 plugin_name = plugin_dir[plugin_dir.index(config['root_plugin_dir']) + len(config['root_plugin_dir']) + 1:]
357 module_name = plugin_name.replace("/", config['module_name_separator']).replace("\\", config['module_name_separator'])
358 plugin_name = plugin_name.replace("/", config['plugin_name_separator']).replace("\\", config['plugin_name_separator'])
359
360
361 plugin_file= os.path.join(plugin_dir,config['plugin_ini_fname'])
362 plugin_defaults= dict(sources="%s.cc" % short_name,
363 headers="",
364 install_headers="",
365 cflags="",
366 cppflags="",
367 cxxflags="",
368 libs="",
369 ldflags="",
370 author="",
371 title="",
372 description="",
373 license="PLUGIN_LICENSE_GPL",
374 name=plugin_name,
375 module_name=module_name,
376 load_by_default=config['default_load_by_default'],
377 disabled="False",
378 static="False",
379 dependencies="",
380 dependency_aliases="",
381 tests="",
382 install=config['default_install'])
383 parser=ConfigParser.ConfigParser(defaults= plugin_defaults)
384 parser.read(plugin_file)
385 plugin=dict(parser.items('plugin'))
386 plugin['plugin_dir'] = plugin_dir
387 if plugin_dir == '.':
388 if not plugin.has_key('url'):
389 print "External Plugins are required to specifiy a url"
390 plugin['url']= 'http://launchpad.net/%(name)s' % plugin
391 sys.exit(1)
392 if plugin_dir == '.' and not plugin.has_key('version'):
393 print "External Plugins are required to specifiy a version"
394 sys.exit(1)
395 if not plugin.has_key('version'):
396 plugin['version'] = config['default_plugin_version']
397
398 if plugin.has_key('load_by_default'):
399 plugin['load_by_default']=parser.getboolean('plugin','load_by_default')
400 if plugin.has_key('disabled'):
401 plugin['disabled']=parser.getboolean('plugin','disabled')
402 if plugin['disabled']:
403 plugin['enabled']="no"
404 else:
405 plugin['enabled']="yes"
406 if plugin.has_key('static'):
407 plugin['static']= parser.getboolean('plugin','static')
408 if plugin.has_key('install'):
409 plugin['install']= parser.getboolean('plugin','install')
410 if plugin.has_key('testsuite'):
411 if plugin['testsuite'] == 'disable':
412 plugin['testsuite']= False
413 else:
414 plugin_testsuite= find_testsuite(plugin_dir)
415 plugin['testsuitedir']=plugin_testsuite
416 if plugin_testsuite is not None:
417 plugin['testsuite']=True
418 else:
419 plugin['testsuite']=False
420
421 plugin['cflags']+= ' ' + config['extra_cflags']
422 plugin['cppflags']+= ' ' + config['extra_cppflags']
423 plugin['cxxflags']+= ' ' + config['extra_cxxflags']
424
425 plugin['libname']= "lib%s%s%s" % (config['plugin_prefix'],
426 plugin['name'],
427 config['plugin_suffix'])
428 if config['force_lowercase_libname']:
429 plugin['libname']= plugin['libname'].lower()
430
431 plugin['root_plugin_dir']= config['root_plugin_dir']
432 plugin['plugin_prefix']= config['plugin_prefix']
433 plugin['plugin_suffix']= config['plugin_suffix']
434 plugin['pkgplugindir']= config['pkgplugindir']
435
436 # Dependencies must have a module but dependency aliases are simply added
437 # to the variable passed during compile.
438 plugin['dependency_list'] = plugin['dependencies'].split()
439 dependency_aliases = plugin['dependency_aliases'].split()
440 plugin['dependencies'] = ','.join(plugin['dependency_list'] +
441 plugin['dependency_aliases'].split())
442 dependency_libs = ["%s/lib%s%s.la" % (config['root_plugin_dir'],
443 dependency.lower().replace('::', '_'),
444 config['plugin_suffix'])
445 for dependency in plugin['dependency_list']]
446 plugin['libs'] = " ".join(plugin['libs'].split() + dependency_libs);
447
448 # Libtool is going to expand:
449 # -DPANDORA_MODULE_AUTHOR='"Padraig O'"'"'Sullivan"'
450 # to:
451 # "-DPANDORA_MODULE_AUTHOR=\"Padraig O'Sullivan\""
452 # So we have to replace internal ''s to '"'"'
453 for key in ('author','title','description','version'):
454 plugin[key]=plugin[key].replace('"','\\"')
455 plugin[key]=plugin[key].replace("'","'\"'\"'")
456 return plugin
457
458
459 def write_plugin_am(plugin, plugin_am):
460 """Write an automake fragment for this plugin.
461
462 :param plugin: The plugin dict.
463 :param plugin_am: The file to write to.
464 """
465 # The .plugin.ini.stamp avoids changing the datestamp on plugin.ini which can
466 # confuse VCS systems.
467 plugin_am.write("""
468 EXTRA_DIST += %(rel_path)s/plugin.ini
469
470 # Prevent errors when a plugin dir is removed
471 %(rel_path)s/plugin.ini:
472
473 """ % plugin)
474 if plugin['headers'] != "":
475 plugin_am.write("noinst_HEADERS += %(headers)s\n" % plugin)
476 if plugin['install_headers'] != "":
477 plugin_am.write("nobase_include_HEADERS += %(install_headers)s\n" % plugin)
478 if plugin['testsuite']:
479 if plugin.has_key('testsuitedir') and plugin['testsuitedir'] != "":
480 plugin_am.write("EXTRA_DIST += %(rel_path)s/%(testsuitedir)s\n" % plugin)
481 if plugin['static']:
482 plugin_am.write("""
483 %(root_plugin_dir)s_%(plugin_prefix)s%(name)s_dir=${top_srcdir}/%(rel_path)s
484 EXTRA_DIST += %(rel_path)s/plugin.ini
485 if %(build_conditional_tag)s
486 noinst_LTLIBRARIES+=%(root_plugin_dir)s/%(libname)s.la
487 %(root_plugin_dir)s_%(libname)s_la_LIBADD=%(libs)s
488 %(root_plugin_dir)s_%(libname)s_la_DEPENDENCIES=%(libs)s
489 %(root_plugin_dir)s_%(libname)s_la_LDFLAGS=$(AM_LDFLAGS) %(ldflags)s $(GCOV_LIBS)
490 %(root_plugin_dir)s_%(libname)s_la_CPPFLAGS=$(AM_CPPFLAGS) -DPANDORA_MODULE_NAME=%(module_name)s -DPANDORA_MODULE_AUTHOR='"%(author)s"' -DPANDORA_MODULE_TITLE='"%(title)s"' -DPANDORA_MODULE_VERSION='"%(version)s"' -DPANDORA_MODULE_LICENSE=%(license)s -DPANDORA_MODULE_DEPENDENCIES='"%(dependencies)s"' %(cppflags)s
491 %(root_plugin_dir)s_%(libname)s_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
492 %(root_plugin_dir)s_%(libname)s_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
493 %(root_plugin_dir)s_%(libname)s_la_SOURCES=%(sources)s
494 check_PROGRAMS += %(tests)s
495 PANDORA_DYNAMIC_LDADDS+=${top_builddir}/%(root_plugin_dir)s/%(libname)s.la
496 endif
497 """ % plugin)
498 else:
499 plugin_am.write("""
500 %(root_plugin_dir)s_%(plugin_prefix)s%(name)s_dir=${top_srcdir}/%(rel_path)s
501 EXTRA_DIST += %(rel_path)s/plugin.ini
502 if %(build_conditional_tag)s
503 %(library_type)s_LTLIBRARIES+=%(root_plugin_dir)s/%(libname)s.la
504 %(root_plugin_dir)s_%(libname)s_la_LDFLAGS=-avoid-version -rpath $(pkgplugindir) $(AM_LDFLAGS) %(ldflags)s $(GCOV_LIBS)
505 %(root_plugin_dir)s_%(libname)s_la_LIBADD=%(libs)s
506 %(root_plugin_dir)s_%(libname)s_la_DEPENDENCIES=%(libs)s
507 %(root_plugin_dir)s_%(libname)s_la_CPPFLAGS=$(AM_CPPFLAGS) -DPANDORA_DYNAMIC_PLUGIN -DPANDORA_MODULE_NAME=%(module_name)s -DPANDORA_MODULE_AUTHOR='"%(author)s"' -DPANDORA_MODULE_TITLE='"%(title)s"' -DPANDORA_MODULE_VERSION='"%(version)s"' -DPANDORA_MODULE_LICENSE=%(license)s -DPANDORA_MODULE_DEPENDENCIES='"%(dependencies)s"' %(cppflags)s
508 %(root_plugin_dir)s_%(libname)s_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
509 %(root_plugin_dir)s_%(libname)s_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
510 %(root_plugin_dir)s_%(libname)s_la_SOURCES=%(sources)s
511 check_PROGRAMS += %(tests)s
512 endif
513 """ % plugin)
514 plugin_am_file=os.path.join(plugin['rel_path'],'plugin.am')
515 if os.path.exists(plugin_am_file):
516 plugin_am.write('include %s\n' % plugin_am_file)
517
518 #
519 # MAIN STARTS HERE:
520 #
521
522 # Parse the pandora-plugin config file
523
524 config_defaults= dict(
525 top_srcdir='.',
526 top_builddir='.',
527 plugin_ini_fname='plugin.ini',
528 plugin_prefix='',
529 plugin_suffix='',
530 extra_cflags='',
531 extra_cppflags='',
532 extra_cxxflags='',
533 root_plugin_dir='',
534 pkgplugindir='',
535 default_install='True',
536 default_plugin_version='',
537 default_load_by_default='False',
538 force_lowercase_libname='True',
539 plugin_name_separator='_',
540 module_name_separator='::'
541 )
542
543 config_parser = ConfigParser.ConfigParser(defaults=config_defaults)
544 config_parser.read(pandora_plugin_file)
545 config = dict(config_parser.items('pandora-plugin'))
546 config['force_lowercase_libname']=config_parser.getboolean('pandora-plugin','force_lowercase_libname')
547
548 # I'm 3 seconds away from writing a comprehensive build solution
549 if not os.path.exists('config/pandora_vc_revinfo'):
550 if os.path.exists('.bzr'):
551 bzr_revno= subprocess.Popen(["bzr", "revno"], stdout=subprocess.PIPE).communicate()[0].strip()
552 rev_date= datetime.date.fromtimestamp(time.time())
553 config['default_plugin_version'] = "%d.%02d.%s" % (rev_date.year, rev_date.month, bzr_revno)
554 else:
555 config['default_plugin_version']=datetime.date.fromtimestamp(time.time()).isoformat()
556 else:
557 # need to read config/pandora_vc_revno
558 pandora_vc_revno=open('config/pandora_vc_revinfo','r').read().split()
559 rev_date=""
560 bzr_revno=""
561 for revno_line in pandora_vc_revno:
562 (revno_key,revno_val)= revno_line.split("=")
563 if revno_key == 'PANDORA_VC_REVNO':
564 bzr_revno=revno_val.strip()
565 elif revno_key == 'PANDORA_RELEASE_DATE':
566 rev_date=revno_val.strip()
567
568 config['default_plugin_version'] = "%s.%s" % (rev_date, bzr_revno)
569
570 actions=[]
571 for arg in sys.argv:
572 if arg.startswith('--top_srcdir='):
573 config['top_srcdir']=arg[12:]
574 elif arg.startswith('--top_builddir='):
575 config['top_builddir']=arg[14:]
576 elif arg == "--force-all":
577 actions=['plugin-list','pandora-plugin.am','write']
578 break
579 else:
580 actions.append(arg)
581 if len(actions) == 0:
582 actions.append('write')
583
584 plugin_list=[]
585
586 def accumulate_plugins(arg, dirname, fnames):
587 # plugin_ini_fname is a name in dirname indicating dirname is a plugin.
588 if config['plugin_ini_fname'] in fnames:
589 arg.append(dirname)
590
591 os.path.walk(os.path.join(config['top_srcdir'],
592 config['root_plugin_dir']),
593 accumulate_plugins,
594 plugin_list)
595
596
597 if not os.path.exists("config/pandora-plugin.am") or "write" in actions:
598 plugin_am_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.am'))
599 plugin_am_file.write("""
600 # always the current list, generated every build so keep this lean.
601 # pandora-plugin.list: datestamp preserved list
602 ${srcdir}/config/pandora-plugin.list: .plugin.scan
603 .plugin.scan:
604 @cd ${top_srcdir} && python config/pandora-plugin plugin-list
605
606 # Plugins affect configure; so to prevent configure running twice in a tarball
607 # build (once up front, once with the right list of plugins, we ship the
608 # generated list of plugins and the housekeeping material for that list so it
609 # is likewise not updated.
610 EXTRA_DIST += \
611 config/pandora-plugin.am \
612 config/pandora-plugin.ac \
613 config/pandora-plugin \
614 config/pandora-plugin.ini
615
616
617 # Seed the list of plugin LDADDS which plugins may extend.
618 PANDORA_DYNAMIC_LDADDS=
619
620 # plugin.stamp: graph dominator for creating all per pandora-plugin.ac/am
621 # files. This is invoked when the code to generate such files has altered.""")
622
623 if not os.path.exists("config/pandora-plugin.ac") or "write" in actions:
624 plugin_ac_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.ac'))
625 plugin_ac_file.write("dnl Generated file, run make to rebuild\n")
626
627
628 if os.path.exists('plugin.ini'):
629 # Are we in a plugin dir which wants to have a self-sufficient build system?
630 plugin_list=['.']
631
632 write_external_plugin()
633 else:
634 plugin_list_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.list'))
635 for p in plugin_list:
636 plugin_list_file.write(p)
637 plugin_list_file.write("\n")
638 plugin_list.sort()
639 plugin_list_file.close()
640
641 if not os.path.exists("config/pandora-plugin.am") or 'write' in actions:
642 plugin_am_file.write("\n${top_srcdir}/config/pandora-plugin.am: ${top_srcdir}/config/pandora-plugin.list ${top_srcdir}/config/pandora-plugin ")
643 for plugin_dir in plugin_list:
644 plugin_am_file.write("\\\n\t%s/plugin.ini " % plugin_dir)
645 plugin_am_file.write("\n\tcd ${top_srcdir} && python config/pandora-plugin write\n")
646 plugin_ini_list=[]
647
648 # Load all plugin.ini files first so we can do dependency tracking.
649 for plugin_dir in plugin_list:
650 plugin = read_plugin_ini(plugin_dir)
651 expand_plugin_ini(plugin)
652 plugin_ini_list.append(plugin)
653
654 # Check for duplicates
655 plugin_name_list = [plugin['libname'] for plugin in plugin_ini_list]
656 for plugin in plugin_ini_list:
657 if plugin_name_list.count(plugin['libname']) != 1:
658 print "Duplicate module name %s" % plugin['libname']
659 exit(1)
660
661 for plugin in plugin_ini_list:
662 write_plugin(plugin, plugin_ini_list)
663
664 if plugin_am_file is not None:
665 plugin_am_file.close()
666 if plugin_ac_file is not None:
667 plugin_ac_file.close()