mocfix.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #
  2. # Copyright (c) Contributors to the Open 3D Engine Project.
  3. # For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. #
  8. from __future__ import (absolute_import, division,
  9. print_function, unicode_literals)
  10. import sys
  11. import json
  12. import os
  13. import re
  14. import subprocess
  15. import argparse
  16. mocre = re.compile(r'[\/<"](([^.\/<]*)\.moc)')
  17. alreadyFixedMocre = re.compile(r'[\/<"]moc_(([^.\/<]*)\.cpp)')
  18. includere = re.compile(r'^[\s]*#include[\s]?')
  19. qobjectre = re.compile(r'^[\s]*Q_OBJECT \/\/[\s]*AUTOMOC')
  20. qmocrun_start = '#if !defined(Q_MOC_RUN)'
  21. qmocrun_end = '#endif'
  22. header_extensions = ['.h', '.hxx']
  23. def fixAutoMocHeader(input_file):
  24. try:
  25. with open(input_file, 'r') as source_file:
  26. print("Considering file {} for automoc fix".format(os.path.abspath(input_file)))
  27. fileLines = source_file.readlines()
  28. except (IOError, UnicodeDecodeError) as err:
  29. print('Error reading {}: {}'.format(input_file, err))
  30. return
  31. for line_number in range(0, len(fileLines)):
  32. if fileLines[line_number].find(qmocrun_start) != -1:
  33. print("Already fixed file {}".format(os.path.abspath(input_file)))
  34. break
  35. reResult = qobjectre.search(fileLines[line_number])
  36. if reResult:
  37. fixHFile(input_file)
  38. return
  39. def fixHFile(input_file):
  40. try:
  41. with open(input_file, 'r') as source_file:
  42. print("Considering file {} for header fix".format(os.path.abspath(input_file)))
  43. try:
  44. fileLines = source_file.readlines()
  45. except UnicodeDecodeError as err:
  46. print('Error reading file {}, err: {}'.format(input_file, err))
  47. return
  48. first_include_line_number = -1
  49. last_include_line_number = -1
  50. for line_number in range(0, len(fileLines)):
  51. if fileLines[line_number].find(qmocrun_start) != -1:
  52. # Already injected Q_MOC_RUN guard
  53. print("Already fixed file {}".format(os.path.abspath(input_file)))
  54. break
  55. reResult = includere.search(fileLines[line_number])
  56. if reResult:
  57. if first_include_line_number == -1:
  58. first_include_line_number = line_number
  59. last_include_line_number = line_number
  60. if first_include_line_number != -1 and last_include_line_number != -1:
  61. print('{}:{},{} Inserting Q_MOC_RUN'.format(os.path.abspath(input_file), first_include_line_number, last_include_line_number))
  62. fileLines.insert(last_include_line_number+1, qmocrun_end + '\n')
  63. fileLines.insert(first_include_line_number, qmocrun_start +'\n')
  64. # p4 edit the file
  65. retProcess = subprocess.run(['p4', 'edit', input_file])
  66. if retProcess.returncode != 0:
  67. print('Error opening {}: {}'.format(input_file, retProcess.returncode))
  68. sys.exit(1)
  69. with open(input_file, 'w') as destination_file:
  70. destination_file.writelines(fileLines)
  71. except IOError as err:
  72. print('Error opening {}: {}'.format(input_file, err))
  73. return
  74. def fixCppFile(input_file):
  75. # parse input file
  76. try:
  77. hasEdit = False
  78. with open(input_file, 'r') as source_file:
  79. print("Reading file " + os.path.abspath(input_file))
  80. try:
  81. fileLines = source_file.readlines()
  82. except UnicodeDecodeError as err:
  83. print('Error reading file {}, err: {}'.format(input_file, err))
  84. return
  85. for line_number in range(0, len(fileLines)):
  86. if alreadyFixedMocre.search(fileLines[line_number]):
  87. for h_extension in header_extensions:
  88. if os.path.exists(os.path.splitext(input_file)[0] + h_extension):
  89. fixHFile(os.path.splitext(input_file)[0] + h_extension)
  90. reResult = mocre.search(fileLines[line_number])
  91. while reResult:
  92. # there is a match, we need to replace
  93. hasEdit = True
  94. # replace using the group
  95. newInclude = 'moc_' + reResult.group(2) + '.cpp'
  96. print('{}:{} Converting {} to {} '.format(os.path.abspath(input_file), line_number, reResult.group(1), newInclude))
  97. fileLines[line_number] = fileLines[line_number].replace(reResult.group(1), newInclude)
  98. for h_extension in header_extensions:
  99. if os.path.exists(os.path.splitext(input_file)[0] + h_extension):
  100. fixHFile(os.path.splitext(input_file)[0] + h_extension)
  101. reResult = mocre.search(fileLines[line_number])
  102. if hasEdit:
  103. # p4 edit the file
  104. retProcess = subprocess.run(['p4', 'edit', input_file])
  105. if retProcess.returncode != 0:
  106. print('Error opening {}: {}'.format(input_file, retProcess.returncode))
  107. sys.exit(1)
  108. with open(input_file, 'w') as destination_file:
  109. destination_file.writelines(fileLines)
  110. except IOError as err:
  111. print('Error opening {}: {}'.format(input_file, err))
  112. return
  113. def fileMayRequireFixing(f):
  114. return os.path.splitext(f)[1].lower() == '.cpp'
  115. def main():
  116. """script main function"""
  117. parser = argparse.ArgumentParser(description='This script converts includes of moc files from\n'
  118. '#include .*filename.moc -> #include .*moc_filename.cpp',
  119. formatter_class=argparse.RawTextHelpFormatter)
  120. parser.add_argument('file_or_dir', type=str, nargs='+',
  121. help='list of files or directories to search within for cpp files to fix up moc includes')
  122. args = parser.parse_args()
  123. for input_file in args.file_or_dir:
  124. if os.path.isdir(input_file):
  125. for dp, dn, filenames in os.walk(input_file):
  126. for f in filenames:
  127. extension = os.path.splitext(f)[1]
  128. extension_lower = extension.lower()
  129. if extension_lower == '.cpp':
  130. fixCppFile(os.path.join(dp, f))
  131. elif extension_lower in header_extensions:
  132. fixAutoMocHeader(os.path.join(dp, f))
  133. else:
  134. extension = os.path.splitext(input_file)[1]
  135. extension_lower = extension.lower()
  136. if extension_lower == '.cpp':
  137. fixCppFile(input_file)
  138. elif extension_lower in header_extensions:
  139. fixAutoMocHeader(input_file)
  140. #entrypoint
  141. if __name__ == '__main__':
  142. main()