generate_cmake_sources.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. #!/usr/bin/python
  2. # Script that parses Visual Studio projects and generates a list of source
  3. # and header files used by those projects. The generated files are in CMake
  4. # format. This script is primarily meant to be used by those who use the
  5. # VS projects as their primary workflow, but want to keep the CMake build
  6. # up to date. Simply run this script to re-generate the source/header file
  7. # list in CMakeLists.txt for all projects.
  8. #
  9. # The output is generated as CMakeSources.cmake in every project's sub-directory,
  10. # which is generally included and used by CMakeLists.txt.
  11. #
  12. # This will only generate a list of include/source files, and will not preserve
  13. # any other VS options (like compiler/linker settings). For those you must edit
  14. # CMakeLists.txt manually. This script will however preserve VS filters (folders).
  15. import os
  16. import sys
  17. import shutil
  18. import xml.etree.ElementTree
  19. def getLocalPath(path):
  20. remainingPath = path
  21. localPath = ''
  22. while True:
  23. split = os.path.split(remainingPath)
  24. remainingPath = split[0]
  25. tail = split[1]
  26. if localPath:
  27. localPath = tail + '/' + localPath
  28. else:
  29. localPath = tail;
  30. if tail == 'Source' or tail == 'Include':
  31. break
  32. if not remainingPath:
  33. localPath = os.path.split(path)[1]
  34. break
  35. return localPath
  36. def getFilterVarName(prefix, filter):
  37. output = filter.replace('Source Files\\', 'SRC_')
  38. output = output.replace('Header Files\\', 'INC_')
  39. output = output.replace('Source Files', 'SRC_NOFILTER')
  40. output = output.replace('Header Files', 'INC_NOFILTER')
  41. output = output.replace('\\', '_')
  42. output = output.replace('/', '_')
  43. return prefix + output.upper()
  44. def processEntries(tag, group, filters):
  45. for child in group.iter('{http://schemas.microsoft.com/developer/msbuild/2003}' + tag):
  46. filterElem = child.find('{http://schemas.microsoft.com/developer/msbuild/2003}Filter')
  47. if filterElem is not None:
  48. filterName = filterElem.text
  49. if filterName not in filters:
  50. filters[filterName] = []
  51. filters[filterName].append(getLocalPath(child.get('Include')))
  52. # Process a .filter file and output a corresponding .txt file containing the necessary CMake commands
  53. def processFile(file):
  54. tree = xml.etree.ElementTree.parse(file)
  55. root = tree.getroot()
  56. filters = {}
  57. for group in root.iter('{http://schemas.microsoft.com/developer/msbuild/2003}ItemGroup'):
  58. processEntries('ClInclude', group, filters)
  59. processEntries('ClCompile', group, filters)
  60. outputName = os.path.splitext(file)[0]
  61. outputName = os.path.splitext(outputName)[0]
  62. outputName = os.path.split(outputName)[1]
  63. varPrefix = 'BS_' + outputName.upper() + '_'
  64. outputFolder = '..\\Source\\' + outputName + '\\CMakeSources.cmake'
  65. with open(outputFolder, 'w') as outputFile:
  66. # Output variables containing all the .h and .cpp files
  67. for key in filters.keys():
  68. outputFile.write('set(%s\n' % getFilterVarName(varPrefix, key))
  69. for entry in filters[key]:
  70. outputFile.write('\t\"%s\"\n' % entry)
  71. outputFile.write(')\n\n')
  72. # Output source groups (filters)
  73. for key in filters.keys():
  74. filter = key.replace('\\', '\\\\')
  75. outputFile.write('source_group(\"{0}\" FILES ${{{1}}})\n'.format(filter, getFilterVarName(varPrefix, key)))
  76. outputFile.write('\n')
  77. # Output a variable containing all variables from the previous step so we can use it for compiling
  78. outputFile.write('set(%sSRC\n' % varPrefix)
  79. for key in filters.keys():
  80. outputFile.write('\t${%s}\n' % getFilterVarName(varPrefix, key))
  81. outputFile.write(')')
  82. # Go through all .filter files
  83. def processAllFiles():
  84. solutionFolder = '..\\Build\\VS2015'
  85. for root, dirs, files in os.walk(solutionFolder):
  86. for file in files:
  87. if(file.lower().endswith('.filters')):
  88. filePath = os.path.join(root, file)
  89. processFile(filePath)
  90. processAllFiles()