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