#!/usr/bin/env python # -*- coding: utf-8 -*- from __future__ import absolute_import from __future__ import division from __future__ import print_function import os import io import glob import shutil import random import argparse import sys from string import Template from mimetypes import add_type, guess_type if sys.version_info[0] >= 3: unicode = str platforms = ("win32", "android", "macosx", "ios", "ios_mac", "cmake", "all") def relpath(a, b): try: return os.path.relpath(a, b) except ValueError: pass return a def unixpath(path): return path.replace("\\", "/") def run(args): if args.hello: dest = args.dest local = os.path.dirname(__file__) if not local: local = "." src = local + "/../examples/HelloWorld/src" data = local + "/../examples/HelloWorld/data" try: shutil.copytree(src, dest + "/src") except OSError: pass try: shutil.copytree(data, dest + "/data") except OSError: pass for p in platforms: if p == "all": continue args.type = p args.src = dest + "/src" args.dest = dest + "/proj." + p _run(args) else: _run(args) def _run(args): name = args.name project = "proj." + args.type + "/" values = {"PROJECT": name} text = (".properties", ".cmd", ".mk", ".java", ".sln", ".vcxproj", ".filters", ".user", ".plist", ".pch", ".json", ".pbxproj") for t in text: add_type("text/plain", t) try: os.makedirs(args.dest) except OSError: # print "folder already exists" # return pass templates_path = os.path.dirname(__file__) if not templates_path: templates_path = "." templates_path += "/templates/" ox_path = templates_path + "/../../" root_path = ox_path + "../" root_path = os.path.abspath(root_path) ox_path = os.path.abspath(ox_path) dest_path = os.path.abspath(args.dest) + "/" root_path = relpath(root_path, dest_path) + "/" ox_path = relpath(ox_path, dest_path) + "/" values["OXYGINE"] = unixpath(ox_path) values["ROOT"] = unixpath(root_path) values["PROJECT_LC"] = name.lower() def process(template, relto, path, gl, fn=None): res = "" for src in gl: ext = os.path.splitext(src)[1] if ext in (".icf", ".orig"): continue rel_src_path = relpath(src, relto) data = {"FILE": unixpath(rel_src_path), "FULLFILE": src} if fn: data = fn(data) t = Template(template) res += t.safe_substitute(data) return res SRC = "" INCLUDE = "" data = "../data" abs_data = os.path.normpath(args.dest + "/" + data) data_files_ = sorted(glob.glob(abs_data + "/*")) data_files = [] for d in data_files_: if os.path.splitext(d)[1] in (".dll", ".lib"): continue data_files.append(d) cpp_files = sorted(glob.glob(args.src + "/*.cpp")) h_files = sorted(glob.glob(args.src + "/*.h")) values["PBXBuildFile"] = "" values["PBXFileReference"] = "" values["PBXGroup_src"] = "" values["PBXGroupSupporting"] = "" values["PBXResourcesBuildPhase"] = "" values["PBXSourcesBuildPhase"] = "" if args.src: relto = dest_path if args.type == "android": tmsrc = "${FILE} " relto = dest_path + "/jni/src/" SRC = process(tmsrc, relto, args.src, cpp_files) # INCLUDE = process(tminc, relto, args.src, h_files) if args.type == "cmake" or args.type == "emscripten": tmsrc = "${FILE} " relto = dest_path SRC = process(tmsrc, relto, args.src, cpp_files) INCLUDE = process(tmsrc, relto, args.src, h_files) if args.type == "win32": tmsrc = """""" tminc = """""" SRC = process(tmsrc, relto, args.src, cpp_files) INCLUDE = process(tminc, relto, args.src, h_files) if args.type in ("macosx", "ios", "ios_mac"): r = random.Random() r.seed(1) class Refs(object): def __init__(self): self._refs = [] def getObject(self, file): for ref in self._refs: if ref[0] == file: return ref[1] obj = "" for i in range(24): obj += r.choice("0123456789ABCDEF") self._refs.append((file, obj)) return obj def getFile(self, obj): for ref in self._refs: if ref[1] == obj: return ref[0] raise KeyError globalRefs = Refs() fileRefs = Refs() def fn(values): FILE = values["FILE"] values["GREF"] = globalRefs.getObject(FILE) values["FREF"] = fileRefs.getObject(FILE) values["NAME"] = os.path.split(FILE)[1] FULL_FILE = values["FULLFILE"] tp = "wtf" if os.path.isdir(FULL_FILE): tp = "folder" else: ext = os.path.splitext(FULL_FILE)[1] if ext == ".cpp": tp = "sourcecode.cpp.cpp" if ext == ".h": tp = "sourcecode.c.h" values["TYPE"] = tp return values # 0405A0061872139000BA6557 /* demo in Resources */ = {isa = PBXBuildFile; fileRef = 0405A0021872139000BA6557 /* demo */; }; # 0405A0071872139000BA6557 /* ext in Resources */ = {isa = PBXBuildFile; fileRef = 0405A0031872139000BA6557 /* ext */; }; # 0405A0081872139000BA6557 /* images in Resources */ = {isa = PBXBuildFile; fileRef = 0405A0041872139000BA6557 /* images */; }; # 0405A0091872139000BA6557 /* xmls in Resources */ = {isa = # PBXBuildFile; fileRef = 0405A0051872139000BA6557 /* xmls */; }; # 04A57D601871FF9F0068B1E5 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 04A57D3A1871FF9F0068B1E5 /* main.cpp */; }; # 04A57D621871FF9F0068B1E5 /* example.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 04A57D3C1871FF9F0068B1E5 /* example.cpp */; }; # 04A57D651871FF9F0068B1E5 /* test.cpp in Sources */ = {isa = # PBXBuildFile; fileRef = 04A57D401871FF9F0068B1E5 /* test.cpp */; # }; tm = "\t\t${GREF} /* ${FILE} in Sources */ = {isa = PBXBuildFile; fileRef = ${FREF} /* ${FILE} */; };\n" values["PBXBuildFile"] = process( tm, relto, args.src, cpp_files, fn) values[ "PBXBuildFile"] += process(tm, relto, abs_data, data_files, fn) # 04A57D3A1871FF9F0068B1E5 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = ../../src/main.cpp; sourceTree = ""; }; # 04A57D3C1871FF9F0068B1E5 /* example.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = example.cpp; path = ../../src/example.cpp; sourceTree = ""; }; # 04A57D3E1871FF9F0068B1E5 /* example.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = example.h; path = ../../src/example.h; sourceTree = ""; }; # 04A57D401871FF9F0068B1E5 /* test.cpp */ = {isa = # PBXFileReference; fileEncoding = 4; lastKnownFileType = # sourcecode.cpp.cpp; name = test.cpp; path = ../../src/test.cpp; # sourceTree = ""; }; # 0405A0021872139000BA6557 /* demo */ = {isa = PBXFileReference; lastKnownFileType = folder; name = demo; path = ../../data/demo; sourceTree = ""; }; # 0405A0031872139000BA6557 /* ext */ = {isa = PBXFileReference; lastKnownFileType = folder; name = ext; path = ../../data/ext; sourceTree = ""; }; # 0405A0041872139000BA6557 /* images */ = {isa = PBXFileReference; lastKnownFileType = folder; name = images; path = ../../data/images; sourceTree = ""; }; # 0405A0051872139000BA6557 /* xmls */ = {isa = PBXFileReference; # lastKnownFileType = folder; name = xmls; path = ../../data/xmls; # sourceTree = ""; }; files = [] files.extend(cpp_files) files.extend(h_files) files.extend(data_files) tm = """\t\t${FREF} /* ${FILE} */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = ${TYPE}; name = ${NAME}; path = ${FILE}; sourceTree = ""; };""" + "\n" values["PBXFileReference"] = process( tm, relto, args.src, files, fn) # 04A57D3A1871FF9F0068B1E5 /* main.cpp */, # 04A57D3C1871FF9F0068B1E5 /* example.cpp */, # 04A57D3E1871FF9F0068B1E5 /* example.h */, # 04A57D401871FF9F0068B1E5 /* test.cpp */, tm = "\t\t\t\t${FREF} /* ${NAME} */, \n" files = [] files.extend(cpp_files) files.extend(h_files) values["PBXGroup_src"] = process(tm, relto, args.src, files, fn) # 0405A0021872139000BA6557 /* demo */, # 0405A0031872139000BA6557 /* ext */, # 0405A0041872139000BA6557 /* images */, # 0405A0051872139000BA6557 /* xmls */, values["PBXGroupSupporting"] = process( tm, relto, abs_data, data_files, fn) # 0405A0081872139000BA6557 /* images in Resources */, # 0405A0071872139000BA6557 /* ext in Resources */, # 0405A0061872139000BA6557 /* demo in Resources */, # 0405A0091872139000BA6557 /* xmls in Resources */, tm = "\t\t\t\t${GREF} /* ${NAME} */, \n" values["PBXResourcesBuildPhase"] = process( tm, relto, abs_data, data_files, fn) # 04A57D621871FF9F0068B1E5 /* example.cpp in Sources */, # 04A57D601871FF9F0068B1E5 /* main.cpp in Sources */, # 04A57D651871FF9F0068B1E5 /* test.cpp in Sources */, values["PBXSourcesBuildPhase"] = process( tm, relto, args.src, cpp_files, fn) values["SRC"] = SRC values["INCLUDE"] = INCLUDE values["DATA"] = "../data" def process_folder(path, dest): try: os.mkdir(dest) except OSError: pass for src in os.listdir(path): src_path = path + src t = Template(src) dest_local = t.substitute(**values) if os.path.isdir(src_path): process_folder(src_path + "/", dest + dest_local + "/") continue dest_path = dest + dest_local fname = os.path.split(dest_path)[1] ext = os.path.splitext(dest_path)[1] print("src " + src_path) tp = guess_type(src_path) if ext in (".storyboard", ".gradle", ".xib") or fname == "gradlew": tp = ("text", "") if ext in (".jar", ): tp = ("binary/binary", "") if not tp[0]: print(">>>>>>>>>>" + str(tp)) continue print(tp[0]) q = tp[0].split("/") if q[0] == "text" or q[1] in ("xml", "x-msdos-program", "x-sh"): print("creating file: " + dest_path) src_data = open(src_path, "r").read() t = Template(src_data) dest_data = t.safe_substitute(**values) ext = os.path.splitext(dest_path)[1] if args.type == "ios" or args.type == "macosx" or args.type == "ios_mac" or ext == ".sh": dest_file = io.open(dest_path, "w", newline="\n") try: dest_file.write(dest_data) except TypeError: dest_file.write(unicode(dest_data, encoding='utf-8')) else: dest_file = open(dest_path, "w") dest_file.write(dest_data) shutil.copystat(src_path, dest_path) else: print("copying file: " + dest_path) shutil.copyfile(src_path, dest_path) top_path = templates_path + project + "/" process_folder(top_path, args.dest + "/") if __name__ == "__main__": parser = argparse.ArgumentParser( description="Oxygine project generator") parser.add_argument("-t", "--type", help="Target platform", choices=platforms, default="win32") parser.add_argument( "-s", "--src", help="folder with already created source files", default="") parser.add_argument( "-d", "--dest", help="Destination folder", default=".") parser.add_argument("--hello", help="Generates a full copy of the HelloWorld example targeting all platforms", action="store_true", default=False) parser.add_argument("name", help="Name of the project") args = parser.parse_args() run(args)