~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to config/pandora-plugin

  • Committer: Stewart Smith
  • Date: 2008-11-21 16:06:07 UTC
  • mto: This revision was merged to the branch mainline in revision 593.
  • Revision ID: stewart@flamingspork.com-20081121160607-n6gdlt013spuo54r
remove mysql_frm_type
and fix engines to return correct value from delete_table when table doesn't exist.
(it should be ENOENT).

Also fix up some tests that manipulated frm files by hand. These tests are no longer valid and will need to be rewritten in the not too distant future.

Show diffs side-by-side

added added

removed removed

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