amalgamate.py 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #!/usr/bin/env python
  2. """Amalgamate json-cpp library sources into a single source and header file.
  3. Works with python2.6+ and python3.4+.
  4. Example of invocation (must be invoked from json-cpp top directory):
  5. python amalgamate.py
  6. """
  7. import os
  8. import os.path
  9. import sys
  10. INCLUDE_PATH = "include/json"
  11. SRC_PATH = "src/lib_json"
  12. class AmalgamationFile:
  13. def __init__(self, top_dir):
  14. self.top_dir = top_dir
  15. self.blocks = []
  16. def add_text(self, text):
  17. if not text.endswith("\n"):
  18. text += "\n"
  19. self.blocks.append(text)
  20. def add_file(self, relative_input_path, wrap_in_comment=False):
  21. def add_marker(prefix):
  22. self.add_text("")
  23. self.add_text("// " + "/"*70)
  24. self.add_text("// %s of content of file: %s" % (prefix, relative_input_path.replace("\\","/")))
  25. self.add_text("// " + "/"*70)
  26. self.add_text("")
  27. add_marker("Beginning")
  28. f = open(os.path.join(self.top_dir, relative_input_path), "rt")
  29. content = f.read()
  30. if wrap_in_comment:
  31. content = "/*\n" + content + "\n*/"
  32. self.add_text(content)
  33. f.close()
  34. add_marker("End")
  35. self.add_text("\n\n\n\n")
  36. def get_value(self):
  37. return "".join(self.blocks).replace("\r\n","\n")
  38. def write_to(self, output_path):
  39. output_dir = os.path.dirname(output_path)
  40. if output_dir and not os.path.isdir(output_dir):
  41. os.makedirs(output_dir)
  42. f = open(output_path, "wb")
  43. f.write(str.encode(self.get_value(), 'UTF-8'))
  44. f.close()
  45. def amalgamate_source(source_top_dir=None,
  46. target_source_path=None,
  47. header_include_path=None):
  48. """Produces amalgamated source.
  49. Parameters:
  50. source_top_dir: top-directory
  51. target_source_path: output .cpp path
  52. header_include_path: generated header path relative to target_source_path.
  53. """
  54. print("Amalgamating header...")
  55. header = AmalgamationFile(source_top_dir)
  56. header.add_text("/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).")
  57. header.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
  58. header.add_file("LICENSE", wrap_in_comment=True)
  59. header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED")
  60. header.add_text("# define JSON_AMALGAMATED_H_INCLUDED")
  61. header.add_text("/// If defined, indicates that the source file is amalgamated")
  62. header.add_text("/// to prevent private header inclusion.")
  63. header.add_text("#define JSON_IS_AMALGAMATION")
  64. header.add_file(os.path.join(INCLUDE_PATH, "version.h"))
  65. header.add_file(os.path.join(INCLUDE_PATH, "allocator.h"))
  66. header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
  67. header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
  68. header.add_file(os.path.join(INCLUDE_PATH, "json_features.h"))
  69. header.add_file(os.path.join(INCLUDE_PATH, "value.h"))
  70. header.add_file(os.path.join(INCLUDE_PATH, "reader.h"))
  71. header.add_file(os.path.join(INCLUDE_PATH, "writer.h"))
  72. header.add_file(os.path.join(INCLUDE_PATH, "assertions.h"))
  73. header.add_text("#endif //ifndef JSON_AMALGAMATED_H_INCLUDED")
  74. target_header_path = os.path.join(os.path.dirname(target_source_path), header_include_path)
  75. print("Writing amalgamated header to %r" % target_header_path)
  76. header.write_to(target_header_path)
  77. base, ext = os.path.splitext(header_include_path)
  78. forward_header_include_path = base + "-forwards" + ext
  79. print("Amalgamating forward header...")
  80. header = AmalgamationFile(source_top_dir)
  81. header.add_text("/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).")
  82. header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path)
  83. header.add_text("/// This header provides forward declaration for all JsonCpp types.")
  84. header.add_file("LICENSE", wrap_in_comment=True)
  85. header.add_text("#ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
  86. header.add_text("# define JSON_FORWARD_AMALGAMATED_H_INCLUDED")
  87. header.add_text("/// If defined, indicates that the source file is amalgamated")
  88. header.add_text("/// to prevent private header inclusion.")
  89. header.add_text("#define JSON_IS_AMALGAMATION")
  90. header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
  91. header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
  92. header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
  93. target_forward_header_path = os.path.join(os.path.dirname(target_source_path),
  94. forward_header_include_path)
  95. print("Writing amalgamated forward header to %r" % target_forward_header_path)
  96. header.write_to(target_forward_header_path)
  97. print("Amalgamating source...")
  98. source = AmalgamationFile(source_top_dir)
  99. source.add_text("/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).")
  100. source.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
  101. source.add_file("LICENSE", wrap_in_comment=True)
  102. source.add_text("")
  103. source.add_text('#include "%s"' % header_include_path)
  104. source.add_text("""
  105. #ifndef JSON_IS_AMALGAMATION
  106. #error "Compile with -I PATH_TO_JSON_DIRECTORY"
  107. #endif
  108. """)
  109. source.add_text("")
  110. source.add_file(os.path.join(SRC_PATH, "json_tool.h"))
  111. source.add_file(os.path.join(SRC_PATH, "json_reader.cpp"))
  112. source.add_file(os.path.join(SRC_PATH, "json_valueiterator.inl"))
  113. source.add_file(os.path.join(SRC_PATH, "json_value.cpp"))
  114. source.add_file(os.path.join(SRC_PATH, "json_writer.cpp"))
  115. print("Writing amalgamated source to %r" % target_source_path)
  116. source.write_to(target_source_path)
  117. def main():
  118. usage = """%prog [options]
  119. Generate a single amalgamated source and header file from the sources.
  120. """
  121. from optparse import OptionParser
  122. parser = OptionParser(usage=usage)
  123. parser.allow_interspersed_args = False
  124. parser.add_option("-s", "--source", dest="target_source_path", action="store", default="dist/jsoncpp.cpp",
  125. help="""Output .cpp source path. [Default: %default]""")
  126. parser.add_option("-i", "--include", dest="header_include_path", action="store", default="json/json.h",
  127. help="""Header include path. Used to include the header from the amalgamated source file. [Default: %default]""")
  128. parser.add_option("-t", "--top-dir", dest="top_dir", action="store", default=os.getcwd(),
  129. help="""Source top-directory. [Default: %default]""")
  130. parser.enable_interspersed_args()
  131. options, args = parser.parse_args()
  132. msg = amalgamate_source(source_top_dir=options.top_dir,
  133. target_source_path=options.target_source_path,
  134. header_include_path=options.header_include_path)
  135. if msg:
  136. sys.stderr.write(msg + "\n")
  137. sys.exit(1)
  138. else:
  139. print("Source successfully amalgamated")
  140. if __name__ == "__main__":
  141. main()