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