19
19
# Find plugins in the tree and add them to the build system
21
import os, ConfigParser, sys
21
import ConfigParser, os, sys
25
25
plugin_ini_fname='plugin.ini'
27
autogen_header="This file is generated, re-run %s to rebuild\n" % sys.argv[0]
29
30
class ChangeProtectedFile(object):
31
32
def __init__(self, fname):
33
self.bogus_file= False
32
34
self.real_fname= fname
33
35
self.new_fname= "%s.new" % fname
34
self.new_file= open(self.new_fname,'w')
37
self.new_file= open(self.new_fname,'w+')
36
41
def write(self, text):
37
self.new_file.write(text)
42
if not self.bogus_file:
43
self.new_file.write(text)
39
45
# We've written all of this out into .new files, now we only copy them
40
46
# over the old ones if they are different, so that we don't cause
41
47
# unnecessary recompiles
49
"""Return True if the file had changed."""
53
new_content = self.new_file.read()
43
54
self.new_file.close()
44
if os.system('diff %s %s >/dev/null 2>&1' % (self.new_fname,self.real_fname)):
56
old_file = file(self.real_fname, 'r')
57
old_content = old_file.read()
61
if new_content != old_content:
62
if old_content != None:
46
63
os.unlink(self.real_fname)
49
64
os.rename(self.new_fname, self.real_fname)
51
os.unlink(self.new_fname)
56
top_srcdir=sys.argv[1]
57
top_builddir=top_srcdir
59
top_builddir=sys.argv[2]
61
plugin_ac=ChangeProtectedFile(os.path.join(top_builddir,'config','plugin.ac'))
62
plugin_am=ChangeProtectedFile(os.path.join(top_srcdir,'config','plugin.am'))
64
plugin_ac.write("dnl %s" % autogen_header)
65
plugin_am.write("# %s" % autogen_header)
66
plugin_am.write("PANDORA_DYNAMIC_LDADDS=\n")
68
def accumulate_plugins(arg, dirname, fnames):
69
if plugin_ini_fname in fnames:
73
os.path.walk(os.path.join(top_srcdir,"plugin"),accumulate_plugins,plugin_list)
76
for plugin_dir in plugin_list:
77
plugin_file= os.path.join(plugin_dir,plugin_ini_fname)
78
parser=ConfigParser.ConfigParser(defaults=dict(sources="",headers="", cflags="",cppflags="",cxxflags="", libs="", ldflags="", testsuite=""))
79
parser.read(plugin_file)
80
plugin=dict(parser.items('plugin'))
81
plugin['rel_path']= plugin_dir[len(top_srcdir)+len(os.path.sep):]
82
# TODO: determine path to plugin dir relative to top_srcdir... append it
83
# to source files if they don't already have it
84
if plugin['sources'] == "":
85
plugin['sources']="%s.cc" % plugin['name']
87
for src in plugin['sources'].split():
88
if not src.startswith(plugin['rel_path']):
89
src= os.path.join(plugin['rel_path'], src)
90
new_sources= "%s %s" % (new_sources, src)
91
plugin['sources']= new_sources
94
for header in plugin['headers'].split():
95
if not header.startswith(plugin['rel_path']):
96
header= os.path.join(plugin['rel_path'], header)
97
new_headers= "%s %s" % (new_headers, header)
98
plugin['headers']= new_headers
100
if plugin.has_key('load_by_default'):
101
plugin['load_by_default']=parser.getboolean('plugin','load_by_default')
103
plugin['load_by_default']=False
104
# Make a yes/no version for autoconf help messages
105
if plugin['load_by_default']:
106
plugin['default_yesno']="yes"
108
plugin['default_yesno']="no"
68
os.unlink(self.new_fname)
73
def write_external_plugin():
74
"""Return True if the plugin had changed."""
75
plugin = read_plugin_ini('.')
76
expand_plugin_ini(plugin, '.')
77
plugin_file = ChangeProtectedFile('pandora-plugin.ac')
78
write_plugin_ac(plugin, plugin_file)
79
result = plugin_file.close()
80
plugin_file = ChangeProtectedFile('pandora-plugin.am')
81
write_plugin_am(plugin, plugin_file)
82
# Write some stub configure.ac and Makefile.am files that include the above
83
result = plugin_file.close() or result
86
def write_plugin(plugin_dir):
87
"""Return True if the plugin had changed."""
88
plugin = read_plugin_ini(plugin_dir)
89
expand_plugin_ini(plugin, plugin_dir)
90
write_plugin_ac(plugin, plugin_ac_file)
91
write_plugin_am(plugin, plugin_am_file)
93
def write_plugin_ac(plugin, plugin_ac):
95
# Write plugin config instructions into plugin.ac file.
110
97
plugin_ac_file=os.path.join(plugin['rel_path'],'plugin.ac')
111
plugin_am_file=os.path.join(plugin['rel_path'],'plugin.am')
112
98
plugin_m4_dir=os.path.join(plugin['rel_path'],'m4')
114
99
plugin_m4_files=[]
115
100
if os.path.exists(plugin_m4_dir) and os.path.isdir(plugin_m4_dir):
116
101
for m4_file in os.listdir(plugin_m4_dir):
117
102
if os.path.splitext(m4_file)[-1] == '.m4':
118
103
plugin_m4_files.append(os.path.join(plugin['rel_path'], m4_file))
120
plugin['build_conditional_tag']= "BUILD_%s_PLUGIN" % plugin['name'].upper()
121
plugin['name_with_dashes']= plugin['name'].replace('_','-')
122
if plugin.has_key('build_conditional'):
123
plugin['has_build_conditional']=True
125
plugin['has_build_conditional']=False
126
plugin['build_conditional']='"x${with_%(name)s_plugin}" = "xyes"' %plugin
128
# Turn this on later plugin_lib%(name)s_plugin_la_CPPFLAGS=$(AM_CPPFLAGS) -DPANDORA_DYNAMIC_PLUGIN %(cppflags)s
131
# Write plugin build instructions into plugin.am file.
133
if plugin['headers'] != "":
134
plugin_am.write("noinst_HEADERS += %(headers)s\n" % plugin)
136
plugin_lib%(name)s_dir=${top_srcdir}/%(rel_path)s
137
EXTRA_DIST += %(rel_path)s/plugin.ini
138
if %(build_conditional_tag)s
139
noinst_LTLIBRARIES+=plugin/lib%(name)s_plugin.la
140
plugin_lib%(name)s_plugin_la_LIBADD=%(libs)s
141
plugin_lib%(name)s_plugin_la_DEPENDENCIES=%(libs)s
142
plugin_lib%(name)s_plugin_la_LDFLAGS=$(AM_LDFLAGS) %(ldflags)s
143
plugin_lib%(name)s_plugin_la_CPPFLAGS=$(AM_CPPFLAGS) %(cppflags)s
144
plugin_lib%(name)s_plugin_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
145
plugin_lib%(name)s_plugin_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
147
plugin_lib%(name)s_plugin_la_SOURCES=%(sources)s
148
PANDORA_DYNAMIC_LDADDS+=${top_builddir}/plugin/lib%(name)s_plugin.la
105
dnl Config for %(title)s
151
# Add this once we're actually doing dlopen (and remove -avoid-version if
153
#pkgplugin_LTLIBRARIES+=plugin/lib%(name)s_plugin.la
154
#plugin_lib%(name)s_plugin_la_LDFLAGS=-module -avoid-version -rpath $(pkgplugindir) %(libs)s
157
if os.path.exists(plugin_am_file):
158
plugin_am.write('include %s\n' % plugin_am_file)
161
# Write plugin config instructions into plugin.am file.
163
plugin_ac.write("\n\ndnl Config for %(title)s\n" % plugin)
164
107
for m4_file in plugin_m4_files:
165
108
plugin_ac.write('m4_sinclude([%s])\n' % m4_file)
195
138
AS_IF([test "x$with_%(name)s_plugin" = "xyes"],
198
if plugin['testsuite'] != "":
141
if plugin['testsuite']:
199
142
plugin_ac.write("""
200
pandora_plugin_test_list="%(testsuite)s,${pandora_plugin_test_list}"
143
pandora_plugin_test_list="%(name)s,${pandora_plugin_test_list}"
204
pandora_default_plugin_list="%(name)s,${pandora_default_plugin_list}"
147
#pandora_default_plugin_list="%(name)s,${pandora_default_plugin_list}"
205
149
pandora_builtin_list="builtin_%(name)s_plugin,${pandora_builtin_list}"
206
150
pandora_plugin_libs="${pandora_plugin_libs} \${top_builddir}/plugin/lib%(name)s_plugin.la"
207
151
PANDORA_PLUGIN_DEP_LIBS="${PANDORA_PLUGIN_DEP_LIBS} %(plugin_dep_libs)s"
155
pandora_default_plugin_list="%(name)s,${pandora_default_plugin_list}"
157
plugin_ac.write(" ])\n")
160
def expand_plugin_ini(plugin, plugin_dir):
161
plugin['rel_path']= plugin_dir[len(top_srcdir)+len(os.path.sep):]
162
# TODO: determine path to plugin dir relative to top_srcdir... append it to
163
# source files if they don't already have it
164
if plugin['sources'] == "":
165
plugin['sources']="%s.cc" % plugin['name']
167
for src in plugin['sources'].split():
168
if not src.startswith(plugin['rel_path']):
169
src= os.path.join(plugin['rel_path'], src)
170
new_sources= "%s %s" % (new_sources, src)
171
plugin['sources']= new_sources
174
for header in plugin['headers'].split():
175
if not header.startswith(plugin['rel_path']):
176
header= os.path.join(plugin['rel_path'], header)
177
new_headers= "%s %s" % (new_headers, header)
178
plugin['headers']= new_headers
180
# Make a yes/no version for autoconf help messages
181
if plugin['load_by_default']:
182
plugin['default_yesno']="yes"
184
plugin['default_yesno']="no"
187
plugin['build_conditional_tag']= "BUILD_%s_PLUGIN" % plugin['name'].upper()
188
plugin['name_with_dashes']= plugin['name'].replace('_','-')
189
if plugin.has_key('build_conditional'):
190
plugin['has_build_conditional']=True
192
plugin['has_build_conditional']=False
193
plugin['build_conditional']='"x${with_%(name)s_plugin}" = "xyes"' %plugin
195
def find_testsuite(plugin_dir):
196
for testdir in ['drizzle-tests','tests']:
197
if os.path.isdir(os.path.join(plugin_dir,testdir)):
199
if os.path.isdir(os.path.join('tests','suite',os.path.basename(plugin_dir))):
203
def read_plugin_ini(plugin_dir):
204
plugin_file= os.path.join(plugin_dir,plugin_ini_fname)
205
parser=ConfigParser.ConfigParser(defaults=dict(sources="",headers="", cflags="",cppflags="",cxxflags="", libs="", ldflags=""))
206
parser.read(plugin_file)
207
plugin=dict(parser.items('plugin'))
208
plugin['name']= os.path.basename(plugin_dir)
209
if plugin.has_key('load_by_default'):
210
plugin['load_by_default']=parser.getboolean('plugin','load_by_default')
212
plugin['load_by_default']=False
213
if plugin.has_key('static'):
214
plugin['static']= parser.getboolean('plugin','static')
216
plugin['static']= False
217
if plugin.has_key('testsuite'):
218
if plugin['testsuite'] == 'disable':
219
plugin['testsuite']= False
221
plugin_testsuite= find_testsuite(plugin_dir)
222
plugin['testsuitedir']=plugin_testsuite
223
if plugin_testsuite is not None:
224
plugin['testsuite']=True
226
plugin['testsuite']=False
231
def write_plugin_am(plugin, plugin_am):
232
"""Write an automake fragment for this plugin.
234
:param plugin: The plugin dict.
235
:param plugin_am: The file to write to.
237
# The .plugin.ini.stamp avoids changing the datestamp on plugin.ini which can
238
# confuse VCS systems.
240
EXTRA_DIST += %(rel_path)s/plugin.ini
242
# Prevent errors when a plugin dir is removed
243
%(rel_path)s/plugin.ini:
245
if plugin['headers'] != "":
246
plugin_am.write("noinst_HEADERS += %(headers)s\n" % plugin)
247
if plugin['testsuite']:
248
if plugin.has_key('testsuitedir') and plugin['testsuitedir'] != "":
249
plugin_am.write("EXTRA_DIST += %(rel_path)s/%(testsuitedir)s\n" % plugin)
252
plugin_lib%(name)s_dir=${top_srcdir}/%(rel_path)s
253
EXTRA_DIST += %(rel_path)s/plugin.ini
254
if %(build_conditional_tag)s
255
noinst_LTLIBRARIES+=plugin/lib%(name)s_plugin.la
256
plugin_lib%(name)s_plugin_la_LIBADD=%(libs)s
257
plugin_lib%(name)s_plugin_la_DEPENDENCIES=%(libs)s
258
plugin_lib%(name)s_plugin_la_LDFLAGS=$(AM_LDFLAGS) %(ldflags)s
259
plugin_lib%(name)s_plugin_la_CPPFLAGS=$(AM_CPPFLAGS) -DPANDORA_MODULE_NAME=%(name)s %(cppflags)s
260
plugin_lib%(name)s_plugin_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
261
plugin_lib%(name)s_plugin_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
263
plugin_lib%(name)s_plugin_la_SOURCES=%(sources)s
264
PANDORA_DYNAMIC_LDADDS+=${top_builddir}/plugin/lib%(name)s_plugin.la
269
plugin_lib%(name)s_dir=${top_srcdir}/%(rel_path)s
270
EXTRA_DIST += %(rel_path)s/plugin.ini
271
if %(build_conditional_tag)s
272
pkgplugin_LTLIBRARIES+=plugin/lib%(name)s_plugin.la
273
plugin_lib%(name)s_plugin_la_LDFLAGS=-module -avoid-version -rpath $(pkgplugindir) $(AM_LDFLAGS) %(ldflags)s
274
plugin_lib%(name)s_plugin_la_LIBADD=%(libs)s
275
plugin_lib%(name)s_plugin_la_DEPENDENCIES=%(libs)s
276
plugin_lib%(name)s_plugin_la_CPPFLAGS=$(AM_CPPFLAGS) -DPANDORA_DYNAMIC_PLUGIN -DPANDORA_MODULE_NAME=%(name)s %(cppflags)s
277
plugin_lib%(name)s_plugin_la_CXXFLAGS=$(AM_CXXFLAGS) %(cxxflags)s
278
plugin_lib%(name)s_plugin_la_CFLAGS=$(AM_CFLAGS) %(cflags)s
280
plugin_lib%(name)s_plugin_la_SOURCES=%(sources)s
283
plugin_am_file=os.path.join(plugin['rel_path'],'plugin.am')
284
if os.path.exists(plugin_am_file):
285
plugin_am.write('include %s\n' % plugin_am_file)
291
if arg.startswith('--top_srcdir='):
293
elif arg.startswith('--top_builddir='):
294
top_builddir=arg[14:]
295
elif arg == "--force-all":
296
actions=['plugin-list','pandora-plugin.am','write']
300
if len(actions) == 0:
301
actions.append('write')
303
def accumulate_plugins(arg, dirname, fnames):
304
# plugin_ini_fname is a name in dirname indicating dirname is a plugin.
305
if plugin_ini_fname in fnames:
307
os.path.walk(os.path.join(top_srcdir,"plugin"),accumulate_plugins,plugin_list)
310
if not os.path.exists("config/pandora-plugin.am") or "write" in actions:
311
plugin_am_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.am'))
312
plugin_am_file.write("""
313
# always the current list, generated every build so keep this lean.
314
# plugin.list: datestamp preserved list
315
${srcdir}/config/plugin.list: .plugin.scan
317
@cd ${top_srcdir} && python config/register_plugins.py plugin-list
319
# Plugins affect configure; so to prevent configure running twice in a tarball
320
# build (once up front, once with the right list of plugins, we ship the
321
# generated list of plugins and the housekeeping material for that list so it
322
# is likewise not updated.
324
config/pandora-plugin.am \
325
config/pandora-plugin.ac \
326
config/register_plugins.py
329
# Seed the list of plugin LDADDS which plugins may extend.
330
PANDORA_DYNAMIC_LDADDS=
332
# plugin.stamp: graph dominator for creating all per pandora-plugin.ac/am
333
# files. This is invoked when the code to generate such files has altered.""")
335
if not os.path.exists("config/pandora-plugin.ac") or "write" in actions:
336
plugin_ac_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.ac'))
337
plugin_ac_file.write("dnl Generated file, run make to rebuild\n")
340
if os.path.exists('plugin.ini'):
341
# Are we in a plugin dir which wants to have a self-sufficient build system?
343
write_external_plugin()
345
plugin_list_file = ChangeProtectedFile(os.path.join('config', 'pandora-plugin.list'))
346
for p in plugin_list:
347
plugin_list_file.write(p)
348
plugin_list_file.write("\n")
350
plugin_list_file.close()
352
if not os.path.exists("config/pandora-plugin.am") or 'write' in actions:
353
plugin_am_file.write("\nconfig/pandora-plugin.am: ${top_srcdir}/config/plugin.list ${top_srcdir}/config/register_plugins.py ")
354
for plugin_dir in plugin_list:
355
plugin_am_file.write("\\\n\t%s/plugin.ini " % plugin_dir)
356
plugin_am_file.write("\n\tcd ${top_srcdir} && python config/register_plugins.py write\n")
357
for plugin_dir in plugin_list:
358
write_plugin(plugin_dir)
360
if plugin_am_file is not None:
361
plugin_am_file.close()
362
if plugin_ac_file is not None:
363
plugin_ac_file.close()