3
# Copyright (C) 2009 Sun Microsystems, Inc.
4
# Copyright (C) 2010, 2011 Monty Taylor
6
# This program is free software; you can redistribute it and/or modify
7
# it under the terms of the GNU General Public License as published by
8
# the Free Software Foundation; version 2 of the License.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, write to the Free Software
17
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
pandora_plugin_file = 'config/pandora-plugin.ini'
21
# Find plugins in the tree and add them to the build system
23
import ConfigParser, os, sys
31
class ChangeProtectedFile(object):
33
def __init__(self, fname):
34
self.bogus_file= False
35
self.real_fname= fname
36
self.new_fname= "%s.new" % fname
38
self.new_file= open(self.new_fname,'w+')
42
def write(self, text):
43
if not self.bogus_file:
44
self.new_file.write(text)
46
# We've written all of this out into .new files, now we only copy them
47
# over the old ones if they are different, so that we don't cause
48
# unnecessary recompiles
50
"""Return True if the file had changed."""
54
new_content = self.new_file.read()
57
old_file = file(self.real_fname, 'r')
58
old_content = old_file.read()
62
if new_content != old_content:
63
if old_content != None:
64
os.unlink(self.real_fname)
65
os.rename(self.new_fname, self.real_fname)
69
os.unlink(self.new_fname)
74
def write_external_configure(plugin, plugin_file):
75
"""Write the initial bits of the configure.ac file"""
76
if not os.path.exists('m4'):
79
AC_PREREQ(2.59)dnl Minimum Autoconf version required.
80
AC_INIT([%(name)s],[%(version)s],[%(url)s])
81
AC_CONFIG_SRCDIR([%(main_source)s])
82
AC_CONFIG_AUX_DIR(config)
84
PANDORA_CANONICAL_TARGET(less-warnings, warnings-always-on, require-cxx, force-gcc42,skip-visibility)
86
PANDORA_REQUIRE_LIBPROTOBUF
87
PANDORA_PROTOBUF_REQUIRE_VERSION([2.1.0])
88
PANDORA_REQUIRE_PROTOC
91
PANDORA_REQUIRE_PTHREAD
95
PANDORA_USE_BETTER_MALLOC
100
write_plugin_ac(plugin, plugin_file)
102
plugin_file.write("""
103
AC_CONFIG_FILES(Makefile)
108
echo "Configuration summary for $PACKAGE_NAME version $VERSION $PANDORA_RELEASE_COMMENT"
110
echo " * Installation prefix: $prefix"
111
echo " * System type: $host_vendor-$host_os"
112
echo " * Host CPU: $host_cpu"
113
echo " * C Compiler: $CC_VERSION"
114
echo " * C++ Compiler: $CXX_VERSION"
115
echo " * Debug enabled: $with_debug"
116
echo " * Warnings as failure: $ac_cv_warnings_as_errors"
117
echo " * C++ cstdint location: $ac_cv_cxx_cstdint"
118
echo " * C++ hash_map location: $ac_cv_cxx_hash_map"
119
echo " * C++ hash namespace: $ac_cv_cxx_hash_namespace"
120
echo " * C++ shared_ptr namespace: $ac_cv_shared_ptr_namespace"
126
def write_external_makefile(plugin, plugin_file):
128
plugin_file.write("""
129
ACLOCAL_AMFLAGS = -I m4 --force
130
VERSION=$(PANDORA_RELEASE_VERSION)
132
pkgplugindir=%(pkgplugindir)s
133
EXTRA_DIST = plugin.ini
136
nobase_include_HEADERS=
137
nobase_pkginclude_HEADERS=
144
if plugin['headers'] != "":
145
plugin_file.write("noinst_HEADERS += %(headers)s\n" % plugin)
146
if plugin['install_headers'] != "":
147
plugin_file.write("nobase_pkginclude_HEADERS += %(install_headers)s\n" % plugin)
148
if plugin['testsuite']:
149
if plugin.has_key('testsuitedir') and plugin['testsuitedir'] != "":
150
plugin_file.write("EXTRA_DIST += %(testsuitedir)s\n" % plugin)
151
plugin_file.write("""
152
pkgplugin_LTLIBRARIES=%(libname)s.la
153
%(libname)s_la_LDFLAGS=-avoid-version -rpath $(pkgplugindir) $(AM_LDFLAGS) %(ldflags)s $(GCOV_LIBS)
154
%(libname)s_la_LIBADD=%(libs)s
155
%(libname)s_la_DEPENDENCIES=%(libs)s
156
%(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
157
%(libname)s_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
158
%(libname)s_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
159
%(libname)s_la_SOURCES=%(sources)s
160
check_PROGRAMS += %(tests)s
162
plugin_am_file=os.path.join(plugin['rel_path'],'plugin.am')
163
if os.path.exists(plugin_am_file):
164
plugin_file.write('include %s\n' % plugin_am_file)
166
def write_external_plugin():
167
"""Return True if the plugin had changed."""
168
plugin = read_plugin_ini('.')
169
expand_plugin_ini(plugin)
170
plugin_file = ChangeProtectedFile('configure.ac')
171
write_external_configure(plugin, plugin_file)
172
result = plugin_file.close()
173
plugin_file = ChangeProtectedFile('Makefile.am')
174
write_external_makefile(plugin, plugin_file)
175
# Write some stub configure.ac and Makefile.am files that include the above
176
result = plugin_file.close() or result
179
def write_plugin(plugin, plugin_ini_list):
180
# Since this function is recursive, make sure we're not already in it.
181
if plugin.has_key('writing_status'):
182
if plugin['writing_status'] == 'done':
185
print "Dependency loop detected with %s" % plugin['name']
188
plugin['writing_status'] = 'dependencies'
190
# Write all dependencies first to get around annoying automake bug
191
for dependency in plugin['dependency_list']:
193
for find_plugin in plugin_ini_list:
194
if find_plugin['module_name'] == dependency:
196
write_plugin(find_plugin, plugin_ini_list)
199
print "Could not find dependency %s: %s" % (plugin['name'], dependency)
202
write_plugin_ac(plugin, plugin_ac_file)
203
write_plugin_am(plugin, plugin_am_file)
204
write_plugin_docs(plugin, plugin_doc_index, plugin_am_file)
205
plugin['writing_status'] = 'done'
207
def write_plugin_docs(plugin, doc_index, plugin_am):
208
if plugin['docs'] is not None and os.path.isdir("docs/plugins"):
209
if not os.path.exists(os.path.join("docs/plugins",plugin["name"])):
210
os.symlink(os.path.abspath(plugin["docs"]), os.path.join("docs/plugins",plugin["name"]))
212
%(name)s/index""" % plugin)
214
EXTRA_DIST+=${top_srcdir}/docs/plugins/%(name)s/*.rst
217
def write_plugin_ac(plugin, plugin_ac):
219
# Write plugin config instructions into plugin.ac file.
221
plugin_ac_file=os.path.join(plugin['rel_path'],'plugin.ac')
222
plugin_m4_dir=os.path.join(plugin['rel_path'],'m4')
224
if os.path.exists(plugin_m4_dir) and os.path.isdir(plugin_m4_dir):
225
for m4_file in os.listdir(plugin_m4_dir):
226
if os.path.splitext(m4_file)[-1] == '.m4':
227
plugin_m4_files.append(os.path.join(plugin['rel_path'], m4_file))
229
dnl Config for %(title)s
231
for m4_file in plugin_m4_files:
232
plugin_ac.write('m4_sinclude([%s])\n' % m4_file)
233
plugin['plugin_dep_libs']=" ".join(["\${top_builddir}/%s" % f for f in plugin['libs'].split()])
236
AC_ARG_WITH([%(name_with_dashes)s-plugin],[
237
dnl indented wierd to make the help output correct
238
AS_HELP_STRING([--with-%(name_with_dashes)s-plugin],[Build %(title)s. @<:@default=%(enabled)s@:>@])
239
AS_HELP_STRING([--without-%(name_with_dashes)s-plugin],[Disable building %(title)s])
241
with_%(name)s_plugin="$withval"
242
AS_IF([test "x$with_%(name)s_plugin" = "xyes"],[
243
requested_%(name)s_plugin="yes"
245
requested_%(name)s_plugin="no"
248
with_%(name)s_plugin="%(enabled)s"
249
requested_%(name)s_plugin="no"
251
AC_ARG_WITH([static-%(name_with_dashes)s-plugin],[
252
AS_HELP_STRING([--with-static-%(name_with_dashes)s-plugin],[Build Archive Storage Engine. @<:@default=%(static_yesno)s@:>@])
253
AS_HELP_STRING([--without-static-%(name_with_dashes)s-plugin],[Disable building Archive Storage Engine])
255
with_static_%(name)s_plugin=${withval}
257
with_static_%(name)s_plugin=%(static_yesno)s
259
AS_IF([test "x${with_static_%(name)s_plugin}" = "xyes" -o "x${with_all_static}" = "xyes"],[
260
shared_%(name)s_plugin=no
262
shared_%(name)s_plugin=yes
264
AC_ARG_ENABLE([%(name_with_dashes)s-plugin],[
265
dnl indented wierd to make the help output correct
266
AS_HELP_STRING([--enable-%(name_with_dashes)s-plugin],[Enable loading %(title)s by default. @<:@default=%(default_yesno)s@:>@])
267
AS_HELP_STRING([--disable-%(name_with_dashes)s-plugin],[Disable loading %(title)s by default.])
269
[enable_%(name)s_plugin="$enableval"],
270
[enable_%(name)s_plugin=%(default_yesno)s])
273
if os.path.exists(plugin_ac_file):
274
plugin_ac.write('m4_sinclude([%s])\n' % plugin_ac_file)
275
# The plugin author has specified some check to make to determine
276
# if the plugin can be built. If the plugin is turned on and this
277
# check fails, then configure should error out. If the plugin is not
278
# turned on, then the normal conditional build stuff should just let
279
# it silently not build
280
if plugin['has_build_conditional']:
282
AS_IF([test %(build_conditional)s],
283
[], dnl build_conditional can only negate
285
AS_IF([test "x${requested_%(name)s_plugin}" = "xyes"],
286
[AC_MSG_ERROR([Plugin %(name)s was explicitly requested, yet failed build dependency checks. Aborting!])])
287
with_%(name)s_plugin=no
291
if not plugin['unconditional']:
293
AM_CONDITIONAL([%(static_build_conditional_tag)s],
294
[test %(build_conditional)s -a ! %(shared_build)s])
295
AM_CONDITIONAL([%(shared_build_conditional_tag)s],
296
[test %(build_conditional)s -a %(shared_build)s])
297
AM_CONDITIONAL([%(build_conditional_tag)s],
298
[test %(build_conditional)s])
302
AS_IF([test "x$with_%(name)s_plugin" = "xyes"],[
304
if plugin['testsuite']:
306
pandora_plugin_test_list="%(name)s,${pandora_plugin_test_list}"
309
AS_IF([test "x${with_static_%(name)s_plugin}" = "xyes" -o "x${with_all_static}" = "xyes"],[
311
AS_IF([test "x$enable_%(name)s_plugin" = "xyes"],[
312
pandora_builtin_load_list="%(module_name)s,${pandora_builtin_load_list}"
313
pandora_builtin_load_symbols_list="_drizzled_%(module_name)s_plugin_,${pandora_builtin_load_symbols_list}"
314
PANDORA_PLUGIN_DEP_LIBS="${PANDORA_PLUGIN_DEP_LIBS} %(plugin_dep_libs)s"
316
pandora_builtin_list="%(module_name)s,${pandora_builtin_list}"
317
pandora_builtin_symbols_list="_drizzled_%(module_name)s_plugin_,${pandora_builtin_symbols_list}"
318
pandora_plugin_libs="${pandora_plugin_libs} \${top_builddir}/%(root_plugin_dir)s/%(libname)s.la"
320
AS_IF([test "x$enable_%(name)s_plugin" = "xyes"],[
321
pandora_default_plugin_list="%(name)s,${pandora_default_plugin_list}"
325
plugin_ac.write("])\n")
327
def fix_file_paths(plugin, files):
328
# TODO: determine path to plugin dir relative to top_srcdir... append it to
329
# source files if they don't already have it
331
if plugin['plugin_dir'] != ".":
332
for file in files.split():
333
if not file.startswith(plugin['rel_path']):
334
file= os.path.join(plugin['rel_path'], file)
335
new_files= "%s %s" % (new_files, file)
337
new_files= " ".join(plugin['sources'].split())
342
def expand_plugin_ini(plugin):
343
if plugin['name'] == "**OUT-OF-TREE**":
344
print "Out of tree plugins require the name field to be specified in plugin.ini"
347
if plugin['plugin_dir'] == ".":
348
plugin['rel_path']= plugin['plugin_dir']
349
plugin['unconditional']=True
351
plugin['rel_path']= plugin['plugin_dir'][len(config['top_srcdir'])+len(os.path.sep):]
352
plugin['unconditional']=False
354
plugin['sources']= fix_file_paths(plugin, plugin['sources'])
355
plugin['main_source']= plugin['sources'].split()[0]
356
plugin['headers']= fix_file_paths(plugin, plugin['headers'])
357
plugin['install_headers']= fix_file_paths(plugin, plugin['install_headers'])
358
plugin['tests']= fix_file_paths(plugin, plugin['tests'])
360
# Make a yes/no version for autoconf help messages
361
if plugin['load_by_default']:
362
plugin['default_yesno']="yes"
364
plugin['default_yesno']="no"
366
if plugin.has_key('extra_dist'):
367
plugin['extra_dist']=" ".join([os.path.join(plugin['rel_path'],f) for f in plugin['extra_dist'].split()])
371
plugin['static_yesno']="yes"
373
plugin['static_yesno']="no"
374
plugin['build_conditional_tag']= "BUILD_%s_PLUGIN" % plugin['name'].upper()
375
plugin['shared_build_conditional_tag']= "BUILD_%s_PLUGIN_SHARED" % plugin['name'].upper()
376
plugin['static_build_conditional_tag']= "BUILD_%s_PLUGIN_STATIC" % plugin['name'].upper()
377
plugin['name_with_dashes']= plugin['name'].replace('_','-')
378
if plugin.has_key('build_conditional'):
379
plugin['has_build_conditional']=True
380
plugin['build_conditional']='"x${with_%(name)s_plugin}" = "xyes" -a %(build_conditional)s' % plugin
382
plugin['has_build_conditional']=False
383
plugin['build_conditional']='"x${with_%(name)s_plugin}" = "xyes"' %plugin
384
plugin['shared_build']='"x${shared_%(name)s_plugin}" = "xyes"' %plugin
386
if plugin['install']:
387
plugin['library_type']= 'pkgplugin'
389
plugin['library_type']= 'noinst'
391
def find_testsuite(plugin_dir):
392
for testdir in ['drizzle-tests','tests']:
393
if os.path.isdir(os.path.join(plugin_dir,testdir)):
395
if os.path.isdir(os.path.join('tests','suite',os.path.basename(plugin_dir))):
399
def find_docs(plugin_dir):
400
if os.path.isfile(os.path.join(plugin_dir, "docs", "index.rst")):
401
return os.path.join(plugin_dir, "docs")
403
def read_plugin_ini(plugin_dir):
405
if plugin_dir == ".":
406
plugin_name="**OUT-OF-TREE**"
407
module_name="**OUT-OF-TREE**"
409
sources_default="%s.cc" % os.path.basename(plugin_dir)
410
plugin_name = plugin_dir[plugin_dir.index(config['root_plugin_dir']) + len(config['root_plugin_dir']) + 1:]
411
module_name = plugin_name.replace("/", config['module_name_separator']).replace("\\", config['module_name_separator'])
412
plugin_name = plugin_name.replace("/", config['plugin_name_separator']).replace("\\", config['plugin_name_separator'])
415
plugin_file= os.path.join(plugin_dir,config['plugin_ini_fname'])
416
plugin_defaults= dict(sources=sources_default,
427
license="PLUGIN_LICENSE_GPL",
429
module_name=module_name,
430
load_by_default=config['default_load_by_default'],
434
dependency_aliases="",
436
install=config['default_install'])
437
parser=ConfigParser.ConfigParser(defaults= plugin_defaults)
438
parser.read(plugin_file)
439
plugin=dict(parser.items('plugin'))
440
plugin['plugin_dir'] = plugin_dir
441
if plugin_dir == '.':
442
if not plugin.has_key('url'):
443
print "External Plugins are required to specifiy a url"
444
plugin['url']= 'http://launchpad.net/%(name)s' % plugin
446
if plugin_dir == '.' and not plugin.has_key('version'):
447
print "External Plugins are required to specifiy a version"
449
if not plugin.has_key('version'):
450
plugin['version'] = config['default_plugin_version']
451
if plugin.has_key('load_by_default'):
452
plugin['load_by_default']=parser.getboolean('plugin','load_by_default')
453
if plugin.has_key('disabled'):
454
plugin['disabled']=parser.getboolean('plugin','disabled')
455
if plugin['disabled']:
456
plugin['enabled']="no"
458
plugin['enabled']="yes"
459
if plugin.has_key('static'):
461
plugin['static']= parser.getboolean('plugin','static')
463
if plugin['static'][:5] == os.sys.platform[:5]:
464
plugin['static']= True
466
plugin['static']= False
467
if plugin.has_key('install'):
468
plugin['install']= parser.getboolean('plugin','install')
469
if plugin.has_key('testsuite'):
470
if plugin['testsuite'] == 'disable':
471
plugin['testsuite']= False
472
plugin['dist_testsuite']= find_testsuite(plugin_dir)
474
plugin_testsuite= find_testsuite(plugin_dir)
475
plugin['testsuitedir']=plugin_testsuite
476
if plugin_testsuite is not None:
477
plugin['testsuite']=True
479
plugin['testsuite']=False
480
plugin['docs']= find_docs(plugin_dir)
482
plugin['cflags']+= ' ' + config['extra_cflags']
483
plugin['cppflags']+= ' ' + config['extra_cppflags']
484
plugin['cxxflags']+= ' ' + config['extra_cxxflags']
486
plugin['libname']= "lib%s%s%s" % (config['plugin_prefix'],
488
config['plugin_suffix'])
489
if config['force_lowercase_libname']:
490
plugin['libname']= plugin['libname'].lower()
492
plugin['root_plugin_dir']= config['root_plugin_dir']
493
plugin['plugin_prefix']= config['plugin_prefix']
494
plugin['plugin_suffix']= config['plugin_suffix']
495
plugin['pkgplugindir']= config['pkgplugindir']
497
# Dependencies must have a module but dependency aliases are simply added
498
# to the variable passed during compile.
499
plugin['dependency_list'] = plugin['dependencies'].split()
500
dependency_aliases = plugin['dependency_aliases'].split()
501
plugin['dependencies'] = ','.join(plugin['dependency_list'] +
502
plugin['dependency_aliases'].split())
503
dependency_libs = ["%s/lib%s%s.la" % (config['root_plugin_dir'],
504
dependency.lower().replace('::', '_'),
505
config['plugin_suffix'])
506
for dependency in plugin['dependency_list']]
507
plugin['libs'] = " ".join(plugin['libs'].split() + dependency_libs);
509
# Libtool is going to expand:
510
# -DPANDORA_MODULE_AUTHOR='"Padraig O'"'"'Sullivan"'
512
# "-DPANDORA_MODULE_AUTHOR=\"Padraig O'Sullivan\""
513
# So we have to replace internal ''s to '"'"'
514
for key in ('author','title','description','version'):
515
plugin[key]=plugin[key].replace('"','\\"')
516
plugin[key]=plugin[key].replace("'","'\"'\"'")
520
def write_plugin_am(plugin, plugin_am):
521
"""Write an automake fragment for this plugin.
523
:param plugin: The plugin dict.
524
:param plugin_am: The file to write to.
526
# The .plugin.ini.stamp avoids changing the datestamp on plugin.ini which can
527
# confuse VCS systems.
529
EXTRA_DIST += %(rel_path)s/plugin.ini
531
# Prevent errors when a plugin dir is removed
532
%(rel_path)s/plugin.ini:
535
if plugin.has_key('extra_dist') and plugin['extra_dist'] != "":
536
plugin_am.write("EXTRA_DIST += %(extra_dist)s\n" % plugin)
537
if plugin['headers'] != "":
538
plugin_am.write("noinst_HEADERS += %(headers)s\n" % plugin)
539
if plugin['install_headers'] != "":
540
plugin_am.write("nobase_pkginclude_HEADERS += %(install_headers)s\n" % plugin)
541
if plugin['testsuite']:
542
if plugin.has_key('testsuitedir') and plugin['testsuitedir'] != "":
543
plugin_am.write("EXTRA_DIST += %(rel_path)s/%(testsuitedir)s\n" % plugin)
544
if plugin.has_key('dist_testsuite') and plugin['dist_testsuite'] != "":
545
plugin_am.write("EXTRA_DIST += %(rel_path)s/%(dist_testsuite)s\n" % plugin)
546
if plugin['docs'] is not None:
547
plugin_am.write("EXTRA_DIST += ${top_srcdir}/%(rel_path)s/docs/*.rst\n" % plugin)
549
%(root_plugin_dir)s_%(plugin_prefix)s%(name)s_dir=${top_srcdir}/%(rel_path)s
550
# Include sources in EXTRA_DIST because we might not build this, but we
551
# still want the sources to wind up in a tarball
552
EXTRA_DIST += %(rel_path)s/plugin.ini %(sources)s
553
if %(static_build_conditional_tag)s
554
noinst_LTLIBRARIES+=%(root_plugin_dir)s/%(libname)s.la
555
%(root_plugin_dir)s_%(libname)s_la_LIBADD=%(libs)s
556
%(root_plugin_dir)s_%(libname)s_la_DEPENDENCIES=%(libs)s
557
%(root_plugin_dir)s_%(libname)s_la_LDFLAGS=$(AM_LDFLAGS) %(ldflags)s $(GCOV_LIBS)
558
%(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
559
%(root_plugin_dir)s_%(libname)s_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
560
%(root_plugin_dir)s_%(libname)s_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
561
%(root_plugin_dir)s_%(libname)s_la_SOURCES=%(sources)s
562
check_PROGRAMS += %(tests)s
563
PANDORA_DYNAMIC_LDADDS+=${top_builddir}/%(root_plugin_dir)s/%(libname)s.la
565
EXTRA_DIST += %(rel_path)s/plugin.ini
566
if %(shared_build_conditional_tag)s
567
%(library_type)s_LTLIBRARIES+=%(root_plugin_dir)s/%(libname)s.la
568
%(root_plugin_dir)s_%(libname)s_la_LDFLAGS=-avoid-version -rpath $(pkgplugindir) $(AM_LDFLAGS) %(ldflags)s $(GCOV_LIBS)
569
%(root_plugin_dir)s_%(libname)s_la_LIBADD=%(libs)s
570
%(root_plugin_dir)s_%(libname)s_la_DEPENDENCIES=%(libs)s
571
%(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
572
%(root_plugin_dir)s_%(libname)s_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
573
%(root_plugin_dir)s_%(libname)s_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
574
%(root_plugin_dir)s_%(libname)s_la_SOURCES=%(sources)s
575
check_PROGRAMS += %(tests)s
578
plugin_am_file=os.path.join(plugin['rel_path'],'plugin.am')
579
if os.path.exists(plugin_am_file):
580
plugin_am.write('include %s\n' % plugin_am_file)
586
# Parse the pandora-plugin config file
588
config_defaults= dict(
591
plugin_ini_fname='plugin.ini',
599
default_install='True',
600
default_plugin_version='',
601
default_load_by_default='False',
602
force_lowercase_libname='True',
603
plugin_name_separator='_',
604
module_name_separator='::'
607
config_parser = ConfigParser.ConfigParser(defaults=config_defaults)
608
config_parser.read(pandora_plugin_file)
609
config = dict(config_parser.items('pandora-plugin'))
610
config['force_lowercase_libname']=config_parser.getboolean('pandora-plugin','force_lowercase_libname')
612
# I'm 3 seconds away from writing a comprehensive build solution
613
if not os.path.exists('config/pandora_vc_revinfo'):
614
if os.path.exists('.bzr'):
615
bzr_revno= subprocess.Popen(["bzr", "revno"], stdout=subprocess.PIPE).communicate()[0].strip()
616
rev_date= datetime.date.fromtimestamp(time.time())
617
config['default_plugin_version'] = "%d.%02d.%s" % (rev_date.year, rev_date.month, bzr_revno)
619
config['default_plugin_version']=datetime.date.fromtimestamp(time.time()).isoformat()
621
# need to read config/pandora_vc_revno
622
pandora_vc_revno=open('config/pandora_vc_revinfo','r').read().split()
625
for revno_line in pandora_vc_revno:
626
(revno_key,revno_val)= revno_line.split("=")
627
if revno_key == 'PANDORA_VC_REVNO':
628
bzr_revno=revno_val.strip()
629
elif revno_key == 'PANDORA_RELEASE_DATE':
630
rev_date=revno_val.strip()
632
config['default_plugin_version'] = "%s.%s" % (rev_date, bzr_revno)
636
if arg.startswith('--top_srcdir='):
637
config['top_srcdir']=arg[12:]
638
elif arg.startswith('--top_builddir='):
639
config['top_builddir']=arg[14:]
640
elif arg == "--force-all":
641
actions=['plugin-list','pandora-plugin.am','write']
645
if len(actions) == 0:
646
actions.append('write')
650
def accumulate_plugins(arg, dirname, fnames):
651
# plugin_ini_fname is a name in dirname indicating dirname is a plugin.
652
if config['plugin_ini_fname'] in fnames:
655
os.path.walk(os.path.join(config['top_srcdir'],
656
config['root_plugin_dir']),
660
if not os.path.exists("config/pandora-plugin.am") or "write" in actions:
661
plugin_am_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.am'))
662
plugin_am_file.write("""
663
# always the current list, generated every build so keep this lean.
664
# pandora-plugin.list: datestamp preserved list
665
${srcdir}/config/pandora-plugin.list: .plugin.scan
667
@cd ${top_srcdir} && python config/pandora-plugin plugin-list
669
# Plugins affect configure; so to prevent configure running twice in a tarball
670
# build (once up front, once with the right list of plugins, we ship the
671
# generated list of plugins and the housekeeping material for that list so it
672
# is likewise not updated.
674
config/pandora-plugin.am \
675
config/pandora-plugin.ac \
676
config/pandora-plugin \
677
config/pandora-plugin.ini
680
# Seed the list of plugin LDADDS which plugins may extend.
681
PANDORA_DYNAMIC_LDADDS=
683
# plugin.stamp: graph dominator for creating all per pandora-plugin.ac/am
684
# files. This is invoked when the code to generate such files has altered.""")
686
if not os.path.exists("config/pandora-plugin.ac") or "write" in actions:
687
plugin_ac_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.ac'))
688
plugin_ac_file.write("dnl Generated file, run make to rebuild\n")
689
plugin_ac_file.write("""
690
AC_ARG_WITH([all-static],[
691
AS_HELP_STRING([--with-all-static],[Link all plugins staticly into the server @<:@default=no@:>@])
693
with_all_static="$withval"
699
if os.path.exists("docs/plugins"):
700
if not os.path.exists("docs/plugins/list.rst") or "write" in actions:
701
plugin_doc_index = ChangeProtectedFile("docs/plugins/list.rst")
702
plugin_doc_index.write("""
711
if os.path.exists('plugin.ini'):
712
# Are we in a plugin dir which wants to have a self-sufficient build system?
715
write_external_plugin()
717
plugin_list_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.list'))
718
for p in plugin_list:
719
plugin_list_file.write(p)
720
plugin_list_file.write("\n")
722
plugin_list_file.close()
724
if not os.path.exists("config/pandora-plugin.am") or 'write' in actions:
725
plugin_am_file.write("\n${top_srcdir}/config/pandora-plugin.am: ${top_srcdir}/config/pandora-plugin.list ${top_srcdir}/config/pandora-plugin ")
726
for plugin_dir in plugin_list:
727
plugin_am_file.write("\\\n\t%s/plugin.ini " % plugin_dir)
728
plugin_am_file.write("\n\tcd ${top_srcdir} && python config/pandora-plugin write\n")
731
# Load all plugin.ini files first so we can do dependency tracking.
732
for plugin_dir in plugin_list:
733
plugin = read_plugin_ini(plugin_dir)
734
expand_plugin_ini(plugin)
735
plugin_ini_list.append(plugin)
737
# Check for duplicates
738
plugin_name_list = [plugin['libname'] for plugin in plugin_ini_list]
739
for plugin in plugin_ini_list:
740
if plugin_name_list.count(plugin['libname']) != 1:
741
print "Duplicate module name %s" % plugin['libname']
744
for plugin in plugin_ini_list:
745
write_plugin(plugin, plugin_ini_list)
747
if plugin_am_file is not None:
748
plugin_am_file.close()
749
if plugin_ac_file is not None:
750
plugin_ac_file.close()
751
if plugin_doc_index is not None:
752
plugin_doc_index.close()