Fixed a bug. I forgot how prerequisites work in make.
Example Makefile:
DEPENDS = .depends
DEPLINKS = .depends_ln
MAKEDEPEND = ./makedepend_ly
SRCS = fullscore.ly parts.ly
all: full parts
depend: $(SRCS)
$(MAKEDEPEND) -f$(DEPENDS) -o.ps --linkspaces=$(DEPLINKS) $(SRCS)
clean:
rm -f *.pdf *.ps *.dvi $(DEPENDS)
rm -rf $(DEPLINKS)
full: fullscore.ps
parts: parts.ps
%.ps: %.ly
$(LILYPOND) $(LYFLAGS) --ps $<
%.pdf: %.ly
$(LILYPOND) $(LYFLAGS) --pdf $<
-include $(DEPENDS)
-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'.
-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'
isphony = True
if os.path.exists('makefile'):
outputFile = 'makefile'
else:
outputFile = 'Makefile'
try:
longopts =
['help','file=','include=','onlyinclude=','linkspaces=','append','start=','objsuffix=']
opts, files= getopt.getopt(argv, 'hf:I:Y:as:o:', 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
includePaths+= standardIncludes
objfiles = set()
for file in files:
objfiles.add(os.path.join(os.path.abspath(file)))
# Prevents cycles
checked = set()
# current directory
cd = './'
depends = dict()
for objfile in objfiles:
depends[objfile] = set()
toCheck = set([objfile])
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:
print err
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:
# 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')
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))
f.write(filebase+objsuffix + ': ' + os.path.relpath(file) + '\n\n')
for dep in deps:
f.write(filebase+objsuffix + ': ' + os.path.relpath(dep) + '\n\n')
f.write('\n')
if isphony and False:
f.write('.PHONY '+filebase+objsuffix+'\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
[email protected]
http://lists.gnu.org/mailman/listinfo/lilypond-user