Final version. ? Added options: -i (include), -p (object prefix), and fixed -a (append)
Sorry for the many update messages -cj
#!/usr/local/bin/python # written by CJ Bell """Create dependencies in makefiles for LilyPond scripts Usage: makedepend_ly [options] files... Options: -h / --help Print this message and exit. -f, --file=MAKEFILE Filename. This allows you to specify an alternate makefile in which makedepend_ly can place its output. Specifying ``-'' as the file name (i.e., -f-) sends the output to standard output instead of modifying an existing file. -I, --include=INCLUDEDIR Include directory. This option tells makedepend_ly to prepend INCLUDEDIR to its list of directories to search when it encounters an \include directive. By default, makedepend_ly only searches the standard include directories. -Y, --onlyinclude=INCLUDEDIR Replace all of the standard include directories with the single specified include directory. -o, -objsuffix=SUFFIX Object file suffix. Default is '.ps'. -p, -objprefix=SUFFIX Object file prefix. The prefix is prepended to the name of the object file. This is usually used to designate a different directory for the object file. The default is the empty string. -i, -include=FILE Process FILE as input, and include all the resulting output before processing the regular input file. This has the same affect as if the specified file is an include statement that appears before the very first line of the regular input file. -a, --append Append the dependencies to the end of the file instead of replacing them. -s, --start=STRING Starting string delimiter. This option permits you to specify a different string for makedepend_ly to look for in the makefile. """ import tempfile import os import shutil import sys import getopt import fileinput import re # Pattern used to parse for a lilypond include inclfn = re.compile(r"[ \t]*\\include[ \t]+\"(?P<filename>(?:(?:\\[\"])|[^\"])*)\"") ntPath = 'C:/Program Files/LilyPond/usr/share/lilypond/current/ly' posixPath = '/usr/share/lilypond/current/ly' includePaths = [] standardIncludes = [] if os.path.exists(ntPath): standardIncludes.append(ntPath) if os.path.exists(posixPath): standardIncludes.append(posixPath) if 'relpath' not in dir(os.path): os.path.relpath = lambda p: p ############################################################################## def main(argv): global includePaths linkspaces = False append = False starting_str = '# DO NOT DELETE THIS LINE -- makedepend_ly depends on it.' objsuffix = '.ps' objprefix = '' autoIncludes = set() if os.path.exists('makefile'): outputFile = 'makefile' else: outputFile = 'Makefile' try: longopts = ['help','file=','include=','onlyinclude=','linkspaces=','append','start=','objsuffix=','objprefix=','include='] opts, files= getopt.getopt(argv, 'hf:I:Y:as:o:p:i:', longopts) except getopt.GetoptError: usage() sys.exit(2) for opt, arg in opts: if opt in ("-h", "--help"): usage() sys.exit() if opt in ('-f','--file'): outputFile = arg if opt in ('-I','--include'): if not os.path.exists(arg): print "Included directory " + arg + " doesn't exist" sys.exit(1) includePaths.append(arg) if opt in ('-Y','--onlyinclude'): if not os.path.exists(arg): print "Included directory " + arg + " doesn't exist" sys.exit(1) standardInclude = [arg] if opt == '--linkspaces': linkspaces = True ns_link_dir = arg if opt in ('-a','--append'): append = True if opt in ('-s','--start'): starting_string = arg if opt in ('-o','--objsuffix'): objsuffix = arg if opt in ('-p','--objprefix'): objprefix = arg if opt in ('-i','--include'): autoIncludes.add(os.path.abspath('parts.ly')) includePaths+= standardIncludes objfiles = set() for file in files: objfiles.add(os.path.join(os.path.abspath(file))) # current directory cd = './' depends = dict() for objfile in objfiles: depends[objfile] = set() checked = set() toCheck = set([objfile])|autoIncludes while toCheck: files = toCheck - checked toCheck = set() for file in files: included = parseFile(file, includePaths) depends[objfile]|= included toCheck |= included checked.add(file) # Make links for each filename with a space so it can be referred-to in the # makefile if linkspaces: try: os.mkdir(ns_link_dir) except EnvironmentError, err: if err.errno != 17: pass new_keys = [] for file in depends.keys(): new_keys.append(linkNoSpace(file, ns_link_dir)) new_values = []; for deps in depends.values(): new_deps = [] for file in deps: new_deps.append(linkNoSpace(file, ns_link_dir)) new_values.append(new_deps) depends = dict(zip(new_keys, new_values)) # Output dependencies old_f = None if outputFile == '-': f = sys.stdout else: try: old_f = open(outputFile, 'r') except IOError, err: if err.errno != 2: pass f = open(outputFile, 'w') f.write(starting_str + '\n') else: if not append: # Copy the file up until the starting deliminator f = tempfile.TemporaryFile() startFound = False for line in old_f: f.write(line) if line == starting_str+'\n': startFound = True break if not startFound: f.write('\n' + starting_str + '\n') else: old_f.close() old_f = None f = open(outputFile, 'a') if not f: print "Cannot open " + outputFile + " for writing" sys.exit() for file, deps in depends.items(): (filebase,_) = os.path.splitext(os.path.relpath(file)) target = objprefix + filebase + objsuffix f.write(target + ': ' + os.path.relpath(file) + '\n') for dep in deps: f.write(target + ': ' + os.path.relpath(dep) + '\n') f.write('\n') if old_f: old_f.close() old_f = open(outputFile, 'w') f.seek(0) shutil.copyfileobj(f,old_f) old_f.close() if f != sys.stdout: f.close() # End main ############################################################################## ############################################################################## def usage(): print __doc__ # End usage ############################################################################## ############################################################################## def linkNoSpace(file, basedir): if ' ' not in file: return file new_filename = os.path.basename(file) if os.path.exists(os.path.join(basedir,new_filename)): if os.readlink(os.path.join(basedir,new_filename)) == file: return os.path.join(basedir,new_filename) n = 2 while os.path.exists(os.path.join(basedir,str(n) + '.' + new_filename)): n+= 1 new_filename = str(n) + '.' + new_filename os.symlink(file, os.path.join(basedir,new_filename)) return os.path.join(basedir,new_filename) # End linkNoSpace ############################################################################## ############################################################################## def parseFile(file, includePaths): includes = set() cd = os.path.dirname(file) for line in fileinput.input(file): try: f = parseLine(line, cd, includePaths) except EnvironmentError, err: print "In " + os.path.relpath(file) + ", " + err.strerror + ": " + err.filename else: if f is not None: includes.add(f) return includes # End parseFile ############################################################################## ############################################################################## def parseLine(line, cd, includePaths): global inclfn match = inclfn.match(line) if match is None: return None file = match.group('filename') # cheack each include path, then the file's directory for incl in includePaths+[cd]: f = os.path.join(incl,file) if os.path.exists(os.path.join(incl,file)): return f # included file can't be found raise EnvironmentError(-1,"cannot find included file", file) # End parseLine ############################################################################## if __name__ == "__main__": main(sys.argv[1:])
_______________________________________________ lilypond-user mailing list lilypond-user@gnu.org http://lists.gnu.org/mailman/listinfo/lilypond-user