depcrunch.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #
  2. # Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
  3. # All rights reserved.
  4. # This component and the accompanying materials are made available
  5. # under the terms of the License "Eclipse Public License v1.0"
  6. # which accompanies this distribution, and is available
  7. # at the URL "http://www.eclipse.org/legal/epl-v10.html".
  8. #
  9. # Initial Contributors:
  10. # Nokia Corporation - initial contribution.
  11. #
  12. # Contributors:
  13. #
  14. # Description:
  15. # Minimise the dependencies in a C preprocessor dependency file to
  16. # those that CPP could not find. Then add in an assumption about
  17. # where to find them. Output is assumed to be relevant to only one target
  18. # even if multiple dep files are analysed.
  19. #
  20. import sys
  21. from optparse import OptionParser
  22. import re
  23. class NoTargetException(Exception):
  24. pass
  25. def depcrunch(file,extensions,assume):
  26. target_pattern = r"^\s*(\S+):\s+"
  27. target_re = re.compile(target_pattern)
  28. # Not the use of (?i) in the following expression. re.I seems to cause re.findall
  29. # to not actually find all files matching the extension whereas (?i) provides
  30. # case insensitivity at the right point and it works. Really don't understand this.
  31. extension_pattern = r"\s([^/ \t]+\.((?i)" + "|".join([t for t in extensions]) + r"))\b"
  32. extension_re = re.compile(extension_pattern)
  33. target = None
  34. deps = []
  35. # Read through the dependencies.
  36. for l in file:
  37. l = l.replace("\\","/").rstrip("\n\r")
  38. # Look out for the target name if
  39. # we have not found it yet
  40. if not target:
  41. t = target_re.match(l)
  42. if t:
  43. target = t.groups()[0]
  44. # Look for prerequisites matching the
  45. # extensions. There may be one or more on
  46. # the same line as the target name.
  47. # Don't use re.I - somehow prevents
  48. # all but one match in a line which may have several files
  49. m = extension_re.findall(l)
  50. if m:
  51. deps.extend([d[0] for d in m])
  52. if not target:
  53. raise NoTargetException()
  54. if len(deps) > 0:
  55. print("{0}: \\".format(target))
  56. for d in deps[:-1]:
  57. print (" {0} \\".format(assume + "/" + d))
  58. print (" {0} ".format(assume + "/" + deps[-1]))
  59. ## Command Line Interface ####################################################
  60. parser = OptionParser(prog = "depcrunch",
  61. usage = "%prog [-h | options] [<depfile>]")
  62. parser.add_option("-e", "--extensions",
  63. action="store", dest="extensions", type='string', help="comma separated list of file extensions of missing files to keep in the crunched dep file.")
  64. parser.add_option("-a", "--assume",
  65. action="store", dest="assume", type='string', help="when cpp reports missing dependencies, assume that they are in this directory")
  66. (options, args) = parser.parse_args()
  67. if not options.extensions:
  68. parser.error("you must specify a comma-separated list of file extensions with the -e option.")
  69. sys.exit(1)
  70. if not options.assume:
  71. parser.error("you must specify an 'assumed directory' for correcting missing dependencies with the -a option.")
  72. sys.exit(1)
  73. depfilename="stdin"
  74. if len(args) > 0:
  75. depfilename=args[0]
  76. file = open(depfilename,"r")
  77. else:
  78. file = sys.stdin
  79. try:
  80. depcrunch(file,options.extensions.split(","), options.assume)
  81. except NoTargetException as e:
  82. sys.stderr.write("Target name not found in dependency file\n");
  83. sys.exit(2)
  84. if file != sys.stdin:
  85. file.close()
  86. sys.exit(0)