Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(77)

Side by Side Diff: build/generator/gen_base.py

Issue 989: kwallet final branch SVN Base: http://svn.collab.net/repos/svn/trunk
Patch Set: Created 3 months, 3 weeks ago
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 # 1 #
2 # gen_base.py -- infrastructure for generating makefiles, dependencies, etc. 2 # gen_base.py -- infrastructure for generating makefiles, dependencies, etc.
3 # 3 #
4 4
5 import os 5 import os
6 import sys 6 import sys
7 import string 7 import string
8 import glob 8 import glob
9 import re 9 import re
10 import fileinput 10 import fileinput
11 import ConfigParser 11 import ConfigParser
12 import generator.swig 12 import generator.swig
13 13
14 import getversion 14 import getversion
15 15
16 16
17 def _warning(msg): 17 def _warning(msg):
18 sys.stderr.write("WARNING: %s\n" % msg) 18 sys.stderr.write("WARNING: %s\n" % msg)
19 19
20 def _error(msg): 20 def _error(msg):
21 sys.stderr.write("ERROR: %s\n" % msg) 21 sys.stderr.write("ERROR: %s\n" % msg)
22 sys.exit(1) 22 sys.exit(1)
23 23
24 class GeneratorBase: 24 class GeneratorBase:
25 25
26 # 26 #
27 # Derived classes should define a class attribute named _extension_map. 27 # Derived classes should define a class attribute named _extension_map.
28 # This attribute should be a dictionary of the form: 28 # This attribute should be a dictionary of the form:
29 # { (target-type, file-type): file-extension ...} 29 # { (target-type, file-type): file-extension ...}
30 # 30 #
31 # where: target-type is 'exe', 'lib', ... 31 # where: target-type is 'exe', 'lib', ...
32 # file-type is 'target', 'object', ... 32 # file-type is 'target', 'object', ...
33 # 33 #
34 34
35 def __init__(self, fname, verfname, options=None): 35 def __init__(self, fname, verfname, options=None):
36 # Retrieve major version from the C header, to avoid duplicating it in 36 # Retrieve major version from the C header, to avoid duplicating it in
37 # build.conf - it is required because some file names include it. 37 # build.conf - it is required because some file names include it.
38 try: 38 try:
39 vsn_parser = getversion.Parser() 39 vsn_parser = getversion.Parser()
40 vsn_parser.search('SVN_VER_MAJOR', 'libver') 40 vsn_parser.search('SVN_VER_MAJOR', 'libver')
41 self.version = vsn_parser.parse(verfname).libver 41 self.version = vsn_parser.parse(verfname).libver
42 except: 42 except:
43 raise GenError('Unable to extract version.') 43 raise GenError('Unable to extract version.')
44 44
45 # Read options 45 # Read options
46 self.release_mode = None 46 self.release_mode = None
47 for opt, val in options: 47 for opt, val in options:
48 if opt == '--release': 48 if opt == '--release':
49 self.release_mode = 1 49 self.release_mode = 1
50 50
(...skipping 255 matching lines...) Show 10 above Show 10 below
306 "A build target is a node in our dependency graph." 306 "A build target is a node in our dependency graph."
307 307
308 def __init__(self, name, options, gen_obj): 308 def __init__(self, name, options, gen_obj):
309 self.name = name 309 self.name = name
310 self.gen_obj = gen_obj 310 self.gen_obj = gen_obj
311 self.desc = options.get('description') 311 self.desc = options.get('description')
312 self.path = options.get('path', '') 312 self.path = options.get('path', '')
313 self.add_deps = options.get('add-deps', '') 313 self.add_deps = options.get('add-deps', '')
314 self.add_install_deps = options.get('add-install-deps', '') 314 self.add_install_deps = options.get('add-install-deps', '')
315 self.msvc_name = options.get('msvc-name') # override project name 315 self.msvc_name = options.get('msvc-name') # override project name
316 316
317 def add_dependencies(self): 317 def add_dependencies(self):
318 # subclasses should override to provide behavior, as appropriate 318 # subclasses should override to provide behavior, as appropriate
319 raise NotImplementedError 319 raise NotImplementedError
320 320
321 class Section: 321 class Section:
322 """Represents an individual section of build.conf 322 """Represents an individual section of build.conf
323 323
324 The Section class is sort of a factory class which is responsible for 324 The Section class is sort of a factory class which is responsible for
325 creating and keeping track of Target instances associated with a section 325 creating and keeping track of Target instances associated with a section
326 of the configuration file. By default it only allows one Target per 326 of the configuration file. By default it only allows one Target per
327 section, but subclasses may create multiple Targets. 327 section, but subclasses may create multiple Targets.
328 """ 328 """
329 329
330 def __init__(self, target_class, name, options, gen_obj): 330 def __init__(self, target_class, name, options, gen_obj):
331 self.target_class = target_class 331 self.target_class = target_class
332 self.name = name 332 self.name = name
333 self.options = options 333 self.options = options
334 self.gen_obj = gen_obj 334 self.gen_obj = gen_obj
335 335
336 def create_targets(self): 336 def create_targets(self):
337 """Create target instances""" 337 """Create target instances"""
338 self.target = self.target_class(self.name, self.options, self.gen_obj) 338 self.target = self.target_class(self.name, self.options, self.gen_obj)
339 self.target.add_dependencies() 339 self.target.add_dependencies()
340 340
341 def get_targets(self): 341 def get_targets(self):
342 """Return list of target instances associated with this section""" 342 """Return list of target instances associated with this section"""
343 return [self.target] 343 return [self.target]
344 344
345 def get_dep_targets(self, target): 345 def get_dep_targets(self, target):
346 """Return list of targets from this section that "target" depends on""" 346 """Return list of targets from this section that "target" depends on"""
347 return [self.target] 347 return [self.target]
348 348
349 class TargetLinked(Target): 349 class TargetLinked(Target):
350 "The target is linked (by libtool) against other libraries." 350 "The target is linked (by libtool) against other libraries."
351 351
352 def __init__(self, name, options, gen_obj): 352 def __init__(self, name, options, gen_obj):
353 Target.__init__(self, name, options, gen_obj) 353 Target.__init__(self, name, options, gen_obj)
354 self.install = options.get('install') 354 self.install = options.get('install')
355 self.compile_cmd = options.get('compile-cmd') 355 self.compile_cmd = options.get('compile-cmd')
356 self.sources = options.get('sources', '*.c') 356 self.sources = options.get('sources', '*.c *.cpp')
357 self.link_cmd = options.get('link-cmd', '$(LINK)') 357 self.link_cmd = options.get('link-cmd', '$(LINK)')
358 358
359 self.external_lib = options.get('external-lib') 359 self.external_lib = options.get('external-lib')
360 self.external_project = options.get('external-project') 360 self.external_project = options.get('external-project')
361 self.msvc_libs = string.split(options.get('msvc-libs', '')) 361 self.msvc_libs = string.split(options.get('msvc-libs', ''))
362 362
363 def add_dependencies(self): 363 def add_dependencies(self):
364 if self.external_lib or self.external_project: 364 if self.external_lib or self.external_project:
365 if self.external_project: 365 if self.external_project:
366 self.gen_obj.projects.append(self) 366 self.gen_obj.projects.append(self)
367 return 367 return
368 368
369 # the specified install area depends upon this target 369 # the specified install area depends upon this target
370 self.gen_obj.graph.add(DT_INSTALL, self.install, self) 370 self.gen_obj.graph.add(DT_INSTALL, self.install, self)
371 371
372 sources = _collect_paths(self.sources or '*.c', self.path) 372 sources = _collect_paths(self.sources or '*.c' or '*.cpp', self.path)
373 sources.sort() 373 sources.sort()
374 374
375 for src, reldir in sources: 375 for srcs, reldir in sources:
376 if src[-2:] == '.c': 376 for src in srcs.split(" "):
377 objname = src[:-2] + self.objext 377 if glob.glob(src):
378 elif src[-4:] == '.cpp': 378 if src[-2:] == '.c':
379 objname = src[:-4] + self.objext 379 objname = src[:-2] + self.objext
380 else: 380 elif src[-4:] == '.cpp':
381 raise GenError('ERROR: unknown file extension on ' + src) 381 objname = src[:-4] + self.objext
382 else:
383 raise GenError('ERROR: unknown file extension on ' + src)
382 384
383 ofile = ObjectFile(objname, self.compile_cmd) 385 ofile = ObjectFile(objname, self.compile_cmd)
384 386
385 # object depends upon source 387 # object depends upon source
386 self.gen_obj.graph.add(DT_OBJECT, ofile, SourceFile(src, reldir)) 388 self.gen_obj.graph.add(DT_OBJECT, ofile, SourceFile(src, reldir))
387 389
388 # target (a linked item) depends upon object 390 # target (a linked item) depends upon object
389 self.gen_obj.graph.add(DT_LINK, self.name, ofile) 391 self.gen_obj.graph.add(DT_LINK, self.name, ofile)
390 392
391 # collect all the paths where stuff might get built 393 # collect all the paths where stuff might get built
392 ### we should collect this from the dependency nodes rather than 394 ### we should collect this from the dependency nodes rather than
393 ### the sources. "what dir are you going to put yourself into?" 395 ### the sources. "what dir are you going to put yourself into?"
394 self.gen_obj.target_dirs.append(self.path) 396 self.gen_obj.target_dirs.append(self.path)
395 for pattern in string.split(self.sources): 397 for pattern in string.split(self.sources):
396 dirname = build_path_dirname(pattern) 398 dirname = build_path_dirname(pattern)
397 if dirname: 399 if dirname:
398 self.gen_obj.target_dirs.append(build_path_join(self.path, dirname)) 400 self.gen_obj.target_dirs.append(build_path_join(self.path, dirname))
399 401
400 class TargetExe(TargetLinked): 402 class TargetExe(TargetLinked):
401 def __init__(self, name, options, gen_obj): 403 def __init__(self, name, options, gen_obj):
402 TargetLinked.__init__(self, name, options, gen_obj) 404 TargetLinked.__init__(self, name, options, gen_obj)
403 405
404 if not (self.external_lib or self.external_project): 406 if not (self.external_lib or self.external_project):
405 extmap = self.gen_obj._extension_map 407 extmap = self.gen_obj._extension_map
406 self.objext = extmap['exe', 'object'] 408 self.objext = extmap['exe', 'object']
407 self.filename = build_path_join(self.path, name + extmap['exe', 'target']) 409 self.filename = build_path_join(self.path, name + extmap['exe', 'target'])
408 410
409 self.manpages = options.get('manpages', '') 411 self.manpages = options.get('manpages', '')
410 self.testing = options.get('testing') 412 self.testing = options.get('testing')
411 413
412 def add_dependencies(self): 414 def add_dependencies(self):
413 TargetLinked.add_dependencies(self) 415 TargetLinked.add_dependencies(self)
414 416
415 # collect test programs 417 # collect test programs
416 if self.install == 'test': 418 if self.install == 'test':
417 self.gen_obj.test_deps.append(self.filename) 419 self.gen_obj.test_deps.append(self.filename)
418 if self.testing != 'skip': 420 if self.testing != 'skip':
419 self.gen_obj.test_progs.append(self.filename) 421 self.gen_obj.test_progs.append(self.filename)
420 elif self.install == 'bdb-test': 422 elif self.install == 'bdb-test':
421 self.gen_obj.bdb_test_deps.append(self.filename) 423 self.gen_obj.bdb_test_deps.append(self.filename)
422 if self.testing != 'skip': 424 if self.testing != 'skip':
423 self.gen_obj.bdb_test_progs.append(self.filename) 425 self.gen_obj.bdb_test_progs.append(self.filename)
424 426
425 self.gen_obj.manpages.extend(string.split(self.manpages)) 427 self.gen_obj.manpages.extend(string.split(self.manpages))
426 428
427 class TargetScript(Target): 429 class TargetScript(Target):
428 def add_dependencies(self): 430 def add_dependencies(self):
429 # we don't need to "compile" the sources, so there are no dependencies 431 # we don't need to "compile" the sources, so there are no dependencies
430 # to add here, except to get the script installed in the proper area. 432 # to add here, except to get the script installed in the proper area.
431 # note that the script might itself be generated, but that isn't a 433 # note that the script might itself be generated, but that isn't a
432 # concern here. 434 # concern here.
433 self.gen_obj.graph.add(DT_INSTALL, self.install, self) 435 self.gen_obj.graph.add(DT_INSTALL, self.install, self)
434 436
435 class TargetLib(TargetLinked): 437 class TargetLib(TargetLinked):
436 def __init__(self, name, options, gen_obj): 438 def __init__(self, name, options, gen_obj):
437 TargetLinked.__init__(self, name, options, gen_obj) 439 TargetLinked.__init__(self, name, options, gen_obj)
438 440
439 if not (self.external_lib or self.external_project): 441 if not (self.external_lib or self.external_project):
(...skipping 621 matching lines...) Show 10 above Show 10 below
1061 s = graph.get_sources(DT_LINK, t.name, Target) \ 1063 s = graph.get_sources(DT_LINK, t.name, Target) \
1062 + graph.get_sources(DT_NONLIB, t.name, Target) 1064 + graph.get_sources(DT_NONLIB, t.name, Target)
1063 for d in s: 1065 for d in s:
1064 if d in targets: 1066 if d in targets:
1065 break 1067 break
1066 else: 1068 else:
1067 # no dependencies found in the targets list. this is a good "base" 1069 # no dependencies found in the targets list. this is a good "base"
1068 # to add to the files list now. 1070 # to add to the files list now.
1069 if isinstance(t, TargetJava): 1071 if isinstance(t, TargetJava):
1070 # Java targets have no filename, and we just ignore them. 1072 # Java targets have no filename, and we just ignore them.
1071 pass 1073 pass
1072 elif isinstance(t, TargetI18N): 1074 elif isinstance(t, TargetI18N):
1073 # I18N targets have no filename, we recurse one level deeper, and 1075 # I18N targets have no filename, we recurse one level deeper, and
1074 # get the filenames of their dependencies. 1076 # get the filenames of their dependencies.
1075 s = graph.get_sources(DT_LINK, t.name) 1077 s = graph.get_sources(DT_LINK, t.name)
1076 for d in s: 1078 for d in s:
1077 if d not in targets: 1079 if d not in targets:
1078 files.append(d.filename) 1080 files.append(d.filename)
1079 else: 1081 else:
1080 files.append(t.filename) 1082 files.append(t.filename)
1081 1083
1082 # don't consider this target any more 1084 # don't consider this target any more
1083 targets.remove(t) 1085 targets.remove(t)
1084 1086
1085 # break out of search through targets 1087 # break out of search through targets
1086 break 1088 break
1087 else: 1089 else:
1088 # we went through the entire target list and everything had at least 1090 # we went through the entire target list and everything had at least
1089 # one dependency on another target. thus, we have a circular dependency 1091 # one dependency on another target. thus, we have a circular dependency
1090 # tree. somebody messed up the .conf file, or the app truly does have 1092 # tree. somebody messed up the .conf file, or the app truly does have
1091 # a loop (and if so, they're screwed; libtool can't relink a lib at 1093 # a loop (and if so, they're screwed; libtool can't relink a lib at
1092 # install time if the dependent libs haven't been installed yet) 1094 # install time if the dependent libs haven't been installed yet)
1093 raise CircularDependencies() 1095 raise CircularDependencies()
1094 1096
1095 return files 1097 return files
1096 1098
1097 class CircularDependencies(Exception): 1099 class CircularDependencies(Exception):
1098 pass 1100 pass
1099 1101
1100 def unique(seq): 1102 def unique(seq):
1101 "Eliminate duplicates from a sequence" 1103 "Eliminate duplicates from a sequence"
1102 list = [ ] 1104 list = [ ]
1103 dupes = { } 1105 dupes = { }
1104 for e in seq: 1106 for e in seq:
1105 if not dupes.has_key(e): 1107 if not dupes.has_key(e):
1106 dupes[e] = None 1108 dupes[e] = None
1107 list.append(e) 1109 list.append(e)
1108 return list 1110 return list
1109 1111
1110 ### End of file. 1112 ### End of file.
OLDNEW

Powered by Google App Engine
This is Rietveld r305