def make_tree(src, dest): src = plat.path(src) dest = plat.path(dest) def ignore(dir, files): rv = [ ] for basename in files: fn = os.path.join(dir, basename) relfn = os.path.relpath(fn, src) ignore = False if blacklist.match(relfn): ignore = True if whitelist.match(relfn): ignore = False if ignore: rv.append(basename) return rv shutil.copytree(src, dest, ignore=ignore)
def unpack_ant(interface): if os.path.exists(plat.path("apache-ant")): interface.success("Apache ANT has already been unpacked.") return archive = "apache-ant-1.8.4-bin.tar.gz" unpacked = "apache-ant-1.8.4" url = "http://archive.apache.org/dist/ant/binaries/" + archive interface.info("I'm downloading Apache Ant. This might take a while.") interface.download(url, plat.path(archive)) interface.info("I'm extracting Apache Ant.") def extract(): tf = tarfile.open(plat.path(archive), "r:*") tf.extractall(plat.path(".")) tf.close() interface.background(extract) plat.rename(plat.path(unpacked), plat.path("apache-ant")) interface.success("I've finished unpacking Apache Ant.")
def generate_keys(interface): set_property("key.alias", "android") set_property("key.store.password", "android") set_property("key.alias.password", "android") default_keystore = plat.path("android.keystore").replace("\\", "/") set_property("key.store", default_keystore) if get_property("key.store") != default_keystore: interface.info(__("You set the keystore yourself, so I'll assume it's how you want it.")) return if os.path.exists(plat.path("android.keystore")): interface.info(__("You've already created an Android keystore, so I won't create a new one for you.")) return if not interface.yesno(__("I can create an application signing key for you. Signing an application with this key allows it to be placed in the Android Market and other app stores.\n\nDo you want to create a key?")): return if not interface.yesno(__("I will create the key in the android.keystore file.\n\nYou need to back this file up. If you lose it, you will not be able to upgrade your application.\n\n\You also need to keep the key safe. If evil people get this file, they could make fake versions of your application, and potentially steal your users' data.\n\nWill you make a backup of android.keystore, and keep it in a safe place?")): return org = interface.input(__("Please enter your name or the name of your organization.")) dname = "CN=" + org if not run(interface, plat.keytool, "-genkey", "-keystore", "android.keystore", "-alias", "android", "-keyalg", "RSA", "-keysize", "2048", "-keypass", "android", "-storepass", "android", "-dname", dname, "-validity", "20000", use_path=True): interface.fail(__("Could not create android.keystore. Is keytool in your path?")) interface.success(__("I've finished creating android.keystore. Please back it up, and keep it in a safe place."))
def get_packages(interface): packages = [ ] if not os.path.exists(plat.path("android-sdk/build-tools/" + plat.build_version)): packages.append("build-tools-" + plat.build_version) if not os.path.exists(plat.path("android-sdk/platforms/" + plat.target)): packages.append(plat.target) if not os.path.exists(plat.path("android-sdk/platform-tools/")): packages.append("platform-tools") if packages: interface.info("I'm about to download and install the required Android packages. This might take a while.") if not run_slow(interface, plat.android, "update", "sdk", "-u", "-f", "-a", "-t", ",".join(packages), yes=True): interface.fail("I was unable to install the required Android packages.") interface.info("I'm updating the library packages.") run(interface, plat.android, "update", "project", "-p", plat.path("extras/google/market_licensing/library"), "--target", plat.target) run(interface, plat.android, "update", "project", "-p", plat.path("extras/google/market_apk_expansion/downloader_library"), "--target", plat.target) interface.success("I've finished installing the required Android packages.")
def make_expansion(): zf = zipfile.ZipFile(plat.path(expansion_file), "w", zipfile.ZIP_STORED) zip_directory(zf, "assets") zf.close() # Delete and re-make the assets directory. shutil.rmtree(plat.path("assets")) os.mkdir(plat.path("assets"))
def extract(): if archive.endswith(".tgz"): tf = tarfile.open(plat.path(archive), "r:*") tf.extractall(plat.path(".")) tf.close() else: zf = zipfile.ZipFile(plat.path(archive)) zf.extractall(plat.path(".")) zf.close()
def generate_keys(interface): # Change this method to allow for custom keystore passwords update_properties = True if os.path.exists(plat.path("local.properties")): with open(plat.path("local.properties")) as f: for l in f: if l.startswith("key.store"): update_properties = False if update_properties: f = file(plat.path("local.properties"), "a") print >>f, "key.alias=android" print >>f, "key.store.password=android" print >>f, "key.alias.password=android" print >>f, "key.store=android.keystore" f.close() if os.path.exists(plat.path("android.keystore")): interface.info("You've already created an Android keystore, so I won't create a new one for you.") return if not interface.yesno("""\ I can create an application signing key for you. Signing an application with this key allows it to be placed in the Android Market and other app stores. Do you want to create a key?"""): return if not interface.yesno("""\ I will create the key in the android.keystore file. You need to back this file up. If you lose it, you will not be able to upgrade your application. You also need to keep the key safe. If evil people get this file, they could make fake versions of your application, and potentially steal your users' data. Will you make a backup of android.keystore, and keep it in a safe place?"""): return org = interface.input("Please enter your name or the name of your organization.") dname = "CN=" + org if not run(interface, plat.keytool, "-genkey", "-keystore", "android.keystore", "-alias", "android", "-keyalg", "RSA", "-keysize", "2048", "-keypass", "android", "-storepass", "android", "-dname", dname, "-validity", "20000", use_path=True): interface.fail("Could not create android.keystore. Is keytool in your path?") interface.success("""I've finished creating android.keystore. Please back it up, and keep it in a safe place.""")
def unpack_sdk(interface): if os.path.exists(plat.path("android-sdk")): interface.success("The Android SDK has already been unpacked.") return if "PGS4A_NO_TERMS" not in os.environ: interface.terms("http://developer.android.com/sdk/terms.html", "Do you accept the Android SDK Terms and Conditions?") if plat.windows: archive = "android-sdk_{}-windows.zip".format(plat.sdk_version) unpacked = "android-sdk-windows" elif plat.macintosh: archive = "android-sdk_{}-macosx.zip".format(plat.sdk_version) unpacked = "android-sdk-macosx" elif plat.linux: archive = "android-sdk_{}-linux.tgz".format(plat.sdk_version) unpacked = "android-sdk-linux" url = "http://dl.google.com/android/" + archive interface.info("I'm downloading the Android SDK. This might take a while.") interface.download(url, plat.path(archive)) interface.info("I'm extracting the Android SDK.") def extract(): if archive.endswith(".tgz"): tf = tarfile.open(plat.path(archive), "r:*") tf.extractall(plat.path(".")) tf.close() else: zf = zipfile.ZipFile(plat.path(archive)) # We have to do this because Python has a small (260?) path length # limit on windows, and the Android SDK has a old_cwd = os.getcwd() os.chdir(plat.path(".")) zf.extractall(".") os.chdir(old_cwd) zf.close() interface.background(extract) plat.rename(plat.path(unpacked, replace=False), plat.path("android-sdk")) interface.success("I've finished unpacking the Android SDK.")
def install_sdk(interface): check_java(interface) unpack_ant(interface) unpack_sdk(interface) if plat.macintosh or plat.linux: os.chmod(plat.path("android-sdk/tools/android"), 0755) os.chmod(plat.path("android-sdk/tools/zipalign"), 0755) get_packages(interface) generate_keys(interface) interface.final_success("It looks like you're ready to start packaging games.")
def copy_libs(): """ This copies updated libraries from the prototype to the project each time a build occurs. """ for i in COPIED: project = plat.path("project/" + i) prototype = plat.path("prototype/" + i) if os.path.exists(project): shutil.rmtree(project) shutil.copytree(prototype, project)
def check_java(interface): """ Checks for the presence of a minimally useful java on the user's system. """ interface.info(__("I'm compiling a short test program, to see if you have a working JDK on your system.")) if not run_slow(interface, plat.javac, plat.path("buildlib/CheckJDK8.java"), use_path=True): interface.fail(__("I was unable to use javac to compile a test file. If you haven't installed the Java Development Kit yet, please download it from:\n\nhttp://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html\n\nThe JDK is different from the JRE, so it's possible you have Java without having the JDK. Without a working JDK, I can't continue.")) if not run_slow(interface, plat.java, "-classpath", plat.path("buildlib"), "CheckJDK8", use_path=True): interface.fail(__("The version of Java on your computer does not appear to be JDK 8, which is the only version supported by the Android SDK. If you need to install JDK 8, you can download it from:\n\nhttp://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html\n\nYou can also set the JAVA_HOME environment variable to use a different version of Java.")) interface.success(__("The JDK is present and working. Good!"))
def extract(): zf = FixedZipFile(plat.path(archive)) # We have to do this because Python has a small (260?) path length # limit on windows, and the Android SDK has very long filenames. old_cwd = os.getcwd() os.chdir(plat.path(".")) zf.extractall("Sdk") os.chdir(old_cwd) zf.close()
def distclean(interface): """ Cleans everything back to as it was when RAPT was first distributed. """ if os.path.exists(plat.path("build_renpy.sh")): raise Exception("Can't clean android directory!") def rmdir(name): path = plat.path(name) if os.path.isdir(path): shutil.rmtree(path) def rm(name): path = plat.path(name) if os.path.exists(path): os.unlink(path) rm("buildlib/CheckJDK8.class") rmdir("project") rmdir("bin") try: rmdir("Sdk") except: rm("Sdk")
def snarf(fn): fn = plat.path(fn) if os.path.exists(fn): return open(fn, "r").read().strip() else: return None
def rmdir(name, make): path = plat.path(name) if os.path.isdir(path): shutil.rmtree(path) if make: os.mkdir(path)
def unpack_sdk(interface): if os.path.exists(plat.path("android-sdk")): interface.success("The Android SDK has already been unpacked.") return if "PGS4A_NO_TERMS" not in os.environ: interface.terms("http://developer.android.com/sdk/terms.html", "Do you accept the Android SDK Terms and Conditions?") if plat.windows: archive = "android-sdk_r20-windows.zip" unpacked = "android-sdk-windows" elif plat.macintosh: archive = "android-sdk_r20-macosx.zip" unpacked = "android-sdk-macosx" elif plat.linux: archive = "android-sdk_r20-linux.tgz" unpacked = "android-sdk-linux" url = "http://dl.google.com/android/" + archive interface.info("I'm downloading the Android SDK. This might take a while.") interface.download(url, plat.path(archive)) interface.info("I'm extracting the Android SDK.") def extract(): if archive.endswith(".tgz"): tf = tarfile.open(plat.path(archive), "r:*") tf.extractall(plat.path(".")) tf.close() else: zf = zipfile.ZipFile(plat.path(archive)) zf.extractall(plat.path(".")) zf.close() interface.background(extract) plat.rename(plat.path(unpacked), plat.path("android-sdk")) interface.success("I've finished unpacking the Android SDK.")
def extract(): if archive.endswith(".tgz"): tf = tarfile.open(plat.path(archive), "r:*") tf.extractall(plat.path(".")) tf.close() else: zf = zipfile.ZipFile(plat.path(archive)) # We have to do this because Python has a small (260?) path length # limit on windows, and the Android SDK has a old_cwd = os.getcwd() os.chdir(plat.path(".")) zf.extractall(".") os.chdir(old_cwd) zf.close()
def get_packages(interface): packages = [ ] if not os.path.exists(plat.path("android-sdk/platforms/android-8")): packages.append("android-8") if not os.path.exists(plat.path("android-sdk/platforms/android-15")): packages.append("android-15") if not os.path.exists(plat.path("android-sdk/platform-tools/")): packages.append("platform-tools") if not os.path.exists(plat.path("android-sdk/extras/google/play_licensing")): packages.append("extra-google-play_licensing") if not os.path.exists(plat.path("android-sdk/extras/google/play_apk_expansion")): packages.append("extra-google-play_apk_expansion") if not packages: interface.success("The required Android packages are already installed.") return interface.info("I'm about to download and install the required Android packages. This might take a while.") if not run_slow(interface, plat.android, "update", "sdk", "-u", "-a", "-t", ",".join(packages)): interface.fail("I was unable to install the required Android packages.") interface.info("I'm updating the library packages.") if "extra-google-play_apk_expansion" in packages: with open(plat.path("android-sdk/extras/google/play_apk_expansion/downloader_library/project.properties"), "r") as f: data = f.read() data = data.replace("../market_licensing", "../../play_licensing/library") with open(plat.path("android-sdk/extras/google/play_apk_expansion/downloader_library/project.properties"), "w") as f: f.write(data) run(interface, plat.android, "update", "project", "-p", "android-sdk/extras/google/play_licensing/library") run(interface, plat.android, "update", "project", "-p", "android-sdk/extras/google/play_apk_expansion/downloader_library") if os.path.exists(plat.path("android-sdk/extras/google/play_apk_expansion/downloader_library/res/values-v9")): shutil.rmtree(plat.path("android-sdk/extras/google/play_apk_expansion/downloader_library/res/values-v9")) interface.success("I've finished installing the required Android packages.")
def distclean(interface): """ Cleans everything back to as it was when RAPT was first distributed. """ if os.path.exists(plat.path("build_renpy.sh")): raise Exception("Can't clean android directory!") def rmdir(name, make): path = plat.path(name) if os.path.isdir(path): shutil.rmtree(path) if make: os.mkdir(path) def rm(name): path = plat.path(name) if os.path.exists(path): os.unlink(path) rm("android.keystore") rm("AndroidManifest.xml") rmdir("assets", True) rmdir("bin", True) rm("default.properties") rm("build.xml") rmdir("gen", False) rm("local.properties") rm("proguard-project.txt") rm("project.properties") rmdir("android-sdk", False) rmdir("apache-ant", False) for i in os.listdir(plat.path('.')): if i.endswith(".tgz") or i.endswith(".tar.gz") or i.endswith(".zip"): os.unlink(plat.path(i, replace=False))
def make_assets(): if assets_dir is not None: make_tree(assets_dir, plat.path("assets")) else: os.mkdir(plat.path("assets")) # If we're Ren'Py, rename things. if os.path.exists(plat.path("assets/renpy")): # Ren'Py uses a lot of names that don't work as assets. Auto-rename # them. for dirpath, dirnames, filenames in os.walk(plat.path("assets"), topdown=False): for fn in filenames + dirnames: if fn[0] == ".": continue old = os.path.join(dirpath, fn) new = os.path.join(dirpath, "x-" + fn) plat.rename(old, new)
def zip_directory(zf, dn): """ Zips up the directory `dn`. `zf` is the file to place the contents of the directory into. """ base_dirname = plat.path(dn) for dirname, dirs, files in os.walk(base_dirname): for fn in files: fn = os.path.join(dirname, fn) archive_fn = os.path.join(dn, os.path.relpath(fn, base_dirname)) zf.write(fn, archive_fn)
def render(template, dest, **kwargs): """ Using jinja2, render `template` to the filename `dest`, supplying the keyword arguments as template parameters. """ dest = plat.path(dest) template = environment.get_template(template) text = template.render(**kwargs) f = file(dest, "wb") f.write(text.encode("utf-8")) f.close()
def copy_project(update_always=False): """ This updates the project, if necessary. """ def snarf(fn): fn = plat.path(fn) if os.path.exists(fn): return open(fn, "r").read().strip() else: return None project = plat.path("project") prototype = plat.path("prototype") update = False if not os.path.exists(project): update = True elif update_always: if snarf("project/build.txt") != snarf("prototype/build.txt"): update = True if not update: return lp = snarf("project/local.properties") if os.path.exists(project): shutil.rmtree(project) shutil.copytree(prototype, project) if lp is not None: with open(plat.path("project/local.properties"), "w") as f: f.write(lp + "\n")
def check_java(interface): """ Checks for the presence of a minimally useful java on the user's system. """ interface.info("""\ I'm compiling a short test program, to see if you have a working JDK on your system. """) SOURCE = """\ class test { public static void main(String args[]) { } } """ f = file(plat.path("test.java"), "w") f.write(SOURCE) f.close() if not run_slow(interface, plat.javac, "test.java", use_path=True): interface.fail("""\ I was unable to use javac to compile a test file. If you haven't installed the Java Development Kit yet, please download it from: http://www.oracle.com/technetwork/java/javase/downloads/index.html The JDK is different from the JRE, so it's possible you have Java without having the JDK. Without a working JDK, I can't continue. """) interface.success("The JDK is present and working. Good!") os.unlink(plat.path("test.java")) os.unlink(plat.path("test.class"))
def copy_presplash(directory, name, default): """ Copies the presplash file. """ for ext in [ ".png", ".jpg" ]: fn = os.path.join(directory, name + ext) if os.path.exists(fn): break else: fn = default ext = os.path.splitext(fn)[1] shutil.copy(fn, plat.path("assets/" + name + ext))
def unpack_sdk(interface): if os.path.exists(plat.sdkmanager): interface.success(__("The Android SDK has already been unpacked.")) return if "RAPT_NO_TERMS" not in os.environ: interface.terms("https://developer.android.com/studio/terms", __("Do you accept the Android SDK Terms and Conditions?")) if plat.windows: archive = "sdk-tools-windows-{}.zip".format(plat.sdk_version) elif plat.macintosh: archive = "sdk-tools-darwin-{}.zip".format(plat.sdk_version) elif plat.linux: archive = "sdk-tools-linux-{}.zip".format(plat.sdk_version) url = "https://dl.google.com/android/repository/" + archive interface.info(__("I'm downloading the Android SDK. This might take a while.")) interface.download(url, plat.path(archive)) interface.info(__("I'm extracting the Android SDK.")) def extract(): zf = FixedZipFile(plat.path(archive)) # We have to do this because Python has a small (260?) path length # limit on windows, and the Android SDK has very long filenames. old_cwd = os.getcwd() os.chdir(plat.path(".")) zf.extractall("Sdk") os.chdir(old_cwd) zf.close() interface.background(extract) interface.success(__("I've finished unpacking the Android SDK."))
def edit_file(fn, pattern, line): """ Replaces lines in `fn` that begin with `pattern` with `line`. `line` should not end with a newline - we add it. """ fn = plat.path(fn) lines = [ ] with open(fn, "r") as f: for l in f: if re.match(pattern, l): l = line + "\n" lines.append(l) with open(fn, "w") as f: f.write(''.join(lines))
def extract(): tf = tarfile.open(plat.path(archive), "r:*") tf.extractall(plat.path(".")) tf.close()
def rm(name): path = plat.path(name) if os.path.exists(path): os.unlink(path)
def pack(): make_tar(iface, plat.path("assets/private.mp3"), private_dirs)