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

Reply via email to