Sophie

Sophie

distrib > Mandriva > 2009.1 > x86_64 > media > contrib-backports > by-pkgid > 5449138d6297d4beefc46ffe46a8c51a > files > 410

waf-1.5.11-1mdv2009.1.noarch.rpm

#! /usr/bin/env python

##
# @file
# waf Makefile.am related classed
#
# note: may be a future base of a Makefile.am to scons converter if someone like to write it
#
# (@) 2005 Ralf Habacker  - published under the GPL license
#

import os, re, types, sys, string, shutil, stat, glob

## print a dictionary
def printDict(dict,sep=' = ' ):
	for key in dict.keys():
		print key  + sep + dict[key]


## Makefile.am support class
#
# The class provides methods for the following tasks:
#		- parsing Makefile.am's and collecting targets and defines into class members
#		- extracting library dependencies and linker flags keyed by the related targets
#		- extracting target libraries and programs
#		- collecting detailled lists of libraries dependencies
#
#
class AMFile:
	def __init__(self):
		self.defines = {}
		self.targets = {}
		self.libadds = {}
		self.ldflags = {}
		self.libs    = {}
		self.progs   = {}
		self.sources = {}
		self.includes= {}
		self.headers = {}
		self.data    = {}
		self.datadirs= {}
		self.path    = ''
		self.subdirs = ''

	## read and parse a Makefile.am
	#
	# The resulting lines are stored in the defines and targets class member.
	# note: Multiple lines in a target are separated by '###'
	# @param path - path for Makefile.am
	# @return 0 if file couldn't be read
	#
	def read(self,path):
		try:
			src=open(path, 'r')
		except:
			return 0
		self.path = path

		file  = src.read()
		lines = file.replace('\n\t','###')
		list = lines.replace('\\\n',' ').split('\n')
		for line in list:
			if line[:1] == '#' or len(line) == 0:
				continue

			index = 0
			while line[index].count('#'):
				index = line[index].index('#')
				if line[index:index+3] == "###":
					index += 3

			var = line.split('=')
			if len(var) == 2:
				self.defines[str(var[0]).strip()] = var[1].strip().replace("'",'').replace('\###',' ')
			else:
				target = line.split(':')
				if len(target) == 2:
					single_target = target[1].strip().replace("'",'')
					# TODO: (rh) split into list
					self.targets[str(target[0]).strip()] = single_target
		self.getLibraries()
		self.getPrograms()
		self.getIncludes()
		self.getHeaders()
		self.getSources()
		self.getLibraryDeps()
		self.getLinkerFlags()
		self.getSubdirs()
		self.getData()

		return 1

	## adds library dependencies from another AMFile instance
	#
	# This method is mainly used for an instance collecting definitions
	# from instances from lower levels
	# @param src - AMFile instance, from which the dependencies are imported
	#
	def addLibraryDeps(self,src):
		for key in src.libadds.keys():
			self.libadds[key] = src.libadds[key]

	## adds linker flags from another AMFile instance
	#
	# This method is mainly used for an instance collecting definitions
	# from instances from lower levels
	# @param src - AMFile instance, from which the flags are imported
	#
	def addLinkerFlags(self,src):
		for key in src.ldflags.keys():
			self.ldflags[key] = src.ldflags[key]

	def addSources(self,src):
		for key in src.sources.keys():
			self.sources[key] = src.sources[key]

	def addLibraries(self,src):
		for key in src.libs.keys():
			self.libs[key] = src.libs[key]

	def getSubdirs(self):
		if self.defines.has_key('SUBDIRS'):
			self.subdirs = self.defines['SUBDIRS']
			del self.defines['SUBDIRS']
	## collect all LIBADDS definitions
	#
	# the function store the definitions in the libadds class member keyed
	# by the relating target
	# @return definition list
	#
	def getLibraryDeps(self):
		reg = re.compile("(.*?)_(?:l?a_)?LIBADD$")
		# TODO (rh) fix relative library pathes
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				libadd = self.findRealTargetname(str(result.group(1)))
				if not len(libadd):
					print "WARNING: no corresponding target for libadd item %s \n" % str(result.group(1))
					continue
				self.libadds[libadd] = self.defines[key]
				del self.defines[key]
		return self.libadds

	## collect all LDFLAGS definitions
	#
	# the function store the definitions in the ldflags class member keyed
	# by the relating target
	# @return definition list
	#
	def getLinkerFlags(self):
		reg = re.compile("(.*?)_(?:l?a_)?LDFLAGS$")
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				ldflag = self.findRealTargetname(str(result.group(1)))
				if not len(ldflag):
					print "WARNING: no corresponding target for ldflag item %s \n" % str(result.group(1))
					continue
				self.ldflags[ldflag] = self.defines[key]
				del self.defines[key]
		return self.ldflags

	## collect all LTLIBRARIES definitions
	#
	# the function store the definitions in the libraries class member keyed
	# by the relating target
	# @return definition list
	#
	def getLibraries(self):
		def stripLibname(val):
			reg = re.compile("(?:lib)?(.*)\.l?a$")
			files = val.split()
			retlist = []
			for file in files:
				result=reg.match(file)
				if result:
					retlist.append(str(result.group(1)))
			return ' '.join(retlist)
		reg = re.compile("(.*)(_l?a)?_(?:LT)?LIBRARIES$")
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				libtype = str(result.group(1))
				if not self.libs.has_key(libtype):
					self.libs[libtype] = ""
				self.libs[libtype] = stripLibname(self.defines[key])
				del self.defines[key]
		return self.libs

	def getPrograms(self):
		reg = re.compile("(.*)_PROGRAMS$")
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				progtype = str(result.group(1))
				if not self.progs.has_key(progtype):
					self.progs[progtype] = ""
				self.progs[progtype] = self.defines[key]
				del self.defines[key]
		return self.progs

	def getData(self):
		reg = re.compile("(.*)_DATA$")
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				dat = str(result.group(1))
				self.data[dat] = self.defines[key]
				del self.defines[key]
		for name in self.data.keys():
			if self.defines.has_key(name+"dir"):
				self.datadirs[name] = self.defines[name+"dir"]
				del self.defines[name+"dir"]
			else:
				del self.data[name]

		return self.data

	## collect all SOURCES definitions
	#
	# the function store the definitions in the sources class member keyed
	# by the relating target
	# this function should be called after getPrograms and getLibraries
	# @return definition list
	#
	def getSources(self):
		reg = re.compile("(.*?)METASOURCES$")
		reg = re.compile("(.*?)_(?:l?a_)?SOURCES$")
		# TODO (rh) fix relative library paths
		for key in self.defines.keys():
			if key.endswith('METASOURCES') and self.defines[key] == "AUTO":
				del self.defines[key]
				continue

			result=reg.match(key)
			if result:
				source = self.findRealTargetname(str(result.group(1)))
				if not len(source):
					print "WARNING: no corresponding target for source item %s \n" % str(result.group(1))
					continue
				self.sources[source] = self.defines[key]
				del self.defines[key]
		return self.sources

	def findRealTargetname(self, target):
		def findInDict(dict, target):
			for key in dict.keys():
				targets = dict[key].split()
				if targets.count(target) > 0:
					return 1
			return 0
		if not findInDict(self.progs, target) and not findInDict(self.libs, target):
			if target[:3] == "lib":
				target = target[3:]
				if not findInDict(self.libs, target):
					target = ""
			else:
				target = ""
		return target

	def getIncludes(self):
		#if we've got a dir global includes, save it in self.includes['_DIR_GLOBAL_']
		if self.defines.has_key('INCLUDES'):
			self.defines['_DIR_GLOBAL__INCLUDES'] = self.defines['INCLUDES']
			del self.defines['INCLUDES']
		reg = re.compile("(.*?)_(?:l?a_)?INCLUDES")
		# TODO (rh) fix relative library pathes
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				include = self.findRealTargetname(str(result.group(1)))
				if not len(include):
					include = result.group(1)
				self.includes[include] = self.defines[key]
				del self.defines[key]
		return self.includes

	def convertMakeFileVariable(self, var):
		var = var.strip()
		if var[:2] == '$(' and var[-1:] == ')':
			return var[2:-1]
		else:
			return var

	def getHeaders(self):
		#if we've got a dir global includes, save it in self.headers['_DIR_GLOBAL_']
		if self.defines.has_key('HEADERS'):
			self.defines['_DIR_GLOBAL__HEADERS'] = self.defines['HEADERS']
			del self.defines['HEADERS']
		reg = re.compile("(.*?)_(?:l?a_)?HEADERS")
		# TODO (rh) fix relative library paths
		for key in self.defines.keys():
			result=reg.match(key)
			if result:
				header = self.findRealTargetname(str(result.group(1)))
				if not len(header):
					header = result.group(1)
				self.headers[header] = self.defines[key]
				del self.defines[key]
		return self.headers

	## return a reverse usage list of dependencies
	#
	# The function scannes the recent library definitions and reorganice
	# the resulting list keyed by the used library
	# @return dependency list
	#
	def getReverseLibraryDeps(self):
		alist = {}
		for key in self.libadds.keys():
			for lib in self.libadds[key].split():
				if lib in alist:
					alist[str(lib)] += " " + key
				else:
					alist[str(lib)] = key
		return alist

	def printDefines(self):
		print "### DEFINES:"
		printDict(self.defines,' = ')

	def printTargets(self):
		print "### TARGETS:"
		printDict(self.targets,' : ')

	def printLibraryDeps(self):
		print "### LIBADD:"
		printDict(self.libadds,' : ')

	def printLinkerFlags(self):
		print "### LDFLAGS:"
		printDict(self.ldflags,' : ')

	def printLibraries(self):
		print "### Libraries:"
		printDict(self.libs,' : ')

	def printSources(self):
		print "### Sources:"
		printDict(self.sources,' : ')


def amview():
	uses = 0
	libadds = 0
	ldflags = 0
	defines = 0
	targets = 0
	libs = 0
	sources = 0
	if len(sys.argv) == 1:
		print "amtool [options] Makefile.am [Makefile.am] ..."
		print "list Makefile.am content"
		print "options:"
		print "    --uses print where a library is used"
		print "    --libadd print all LIBADD depenencies "
		print "    --ldflags print all LDFLAGS definitions"
		print "    --defines print all Makefile variables"
		print "    --targets print all Makefile targets"
		print "    --libs print all library definitions"
		print "    --sources print all source definitions"
	else:
		all_ams = AMFile()
		for a in range(1,len(sys.argv)):
			if sys.argv[a][:6] == '--uses':
				uses = 1
			elif sys.argv[a][:8] == '--libadd':
				libadds = 1
			elif sys.argv[a][:9] == '--defines':
				defines = 1
			elif sys.argv[a][:9] == '--targets':
				targets = 1
			elif sys.argv[a][:9] == '--ldflags':
				ldflags = 1
			elif sys.argv[a][:6] == '--libs':
				libs = 1
			elif sys.argv[a][:9] == '--sources':
				sources = 1
			if  libadds or defines or targets or ldflags or libs or sources:
				uses = 2

		for a in range(1,len(sys.argv)):
			if sys.argv[a][:2] == '--':
				continue
			am_file = AMFile()

			if not am_file.read(sys.argv[a]):
				continue

			if uses == 2:
				print "### " + sys.argv[a]

			if defines:
				am_file.printDefines()
			if targets:
				am_file.printTargets()
			if libadds:
				am_file.printLibraryDeps()
			if ldflags:
				am_file.printLinkerFlags()
			if libs:
				am_file.printLibraries()
			if sources:
				am_file.printSources()

			all_ams.addLibraryDeps(am_file)
			all_ams.addLinkerFlags(am_file)
			all_ams.addSources(am_file)
			all_ams.addLibraries(am_file)

		if uses == 0:
			all_ams.printLibraryDeps()
		elif uses == 1:
			a = all_ams.getReverseLibraryDeps()
			printDict(a)