Example #1
0
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.")
Example #2
0
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.")
Example #3
0
def split_renpy(directory):
    """
    Takes a built Ren'Py game, and splits it into the private and assets
    directories. This also renames <game>.py to main.py, and moves common/
    into assets.
    """

    private = os.path.join(directory, "private")
    assets = os.path.join(directory, "assets")

    filenames = os.listdir(directory)

    os.mkdir(private)
    os.mkdir(assets)
    os.mkdir(os.path.join(assets, "renpy"))

    plat.rename(os.path.join(directory, "renpy", "common"), os.path.join(assets, "renpy", "common"))

    for fn in filenames:
        full_fn = os.path.join(directory, fn)

        if fn.startswith("android-"):
            continue

        if fn.endswith(".py"):
            plat.rename(full_fn, os.path.join(private, "main.py"))
            continue

        if fn == "renpy":
            plat.rename(full_fn, os.path.join(private, fn))
            continue

        plat.rename(full_fn, os.path.join(assets, fn))

    return private, assets
Example #4
0
File: build.py Project: renpy/rapt
def split_renpy(directory):
    """
    Takes a built Ren'Py game, and splits it into the private and assets
    directories. This also renames <game>.py to main.py, and moves common/
    into assets.
    """

    private = os.path.join(directory, "private")
    assets = os.path.join(directory, "assets")

    filenames = os.listdir(directory)

    os.mkdir(private)
    os.mkdir(assets)
    os.mkdir(os.path.join(assets, "renpy"))

    plat.rename(os.path.join(directory, "renpy", "common"), os.path.join(assets, "renpy", "common"))

    for fn in filenames:
        full_fn = os.path.join(directory, fn)

        if fn.startswith("android-"):
            continue

        if fn.endswith(".py"):
            plat.rename(full_fn, os.path.join(private, "main.py"))
            continue

        if fn == "renpy":
            plat.rename(full_fn, os.path.join(private, fn))
            continue

        plat.rename(full_fn, os.path.join(assets, fn))

    return private, assets
Example #5
0
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.")
Example #6
0
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))
            zf.extractall(plat.path("."))
            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.")
Example #7
0
    def make_assets():

        if assets_dir is not None:
            make_tree(assets_dir, assets)
        else:
            os.mkdir(assets)

        # If we're Ren'Py, rename things.
        if RENPY:

            # Ren'Py uses a lot of names that don't work as assets. Auto-rename
            # them.
            for dirpath, dirnames, filenames in os.walk(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)
Example #8
0
    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)
Example #9
0
def build(iface, directory, commands, launch=False, finished=None):

    # Modify to ask for a Keystore password if none exists
    # or add setting to build for production

    # Are we doing a Ren'Py build?

    global RENPY
    RENPY = plat.renpy

    if not os.path.isdir(directory):
        iface.fail("{} is not a directory.".format(directory))

    if RENPY and not os.path.isdir(os.path.join(directory, "game")):
        iface.fail("{} does not contain a Ren'Py game.".format(directory))


    config = configure.Configuration(directory)
    if config.package is None:
        iface.fail("Run configure before attempting to build the app.")

    if (config.store == "play" or config.store == "all") and (config.google_play_key is None):
        iface.fail("Google Play support is enabled, but build.google_play_key is not set. Please set in your game.")

    global blacklist
    global whitelist

    blacklist = PatternList("blacklist.txt")
    whitelist = PatternList("whitelist.txt")

    if RENPY:
        manifest_extra = None
        default_icon = plat.path("templates/renpy-icon.png")
        default_presplash = plat.path("templates/renpy-presplash.jpg")

        public_dir = None
        private_dir, assets_dir = split_renpy(directory)

    else:
        manifest_extra = ""
        default_icon = plat.path("templates/pygame-icon.png")
        default_presplash = plat.path("templates/pygame-presplash.jpg")

        if config.layout == "internal":
            private_dir = directory
            public_dir = None
            assets_dir = None
        elif config.layout == "external":
            private_dir = None
            public_dir = directory
            assets_dir = None
        elif config.layout == "split":
            private_dir = join_and_check(directory, "internal")
            public_dir = join_and_check(directory, "external")
            assets_dir = join_and_check(directory, "assets")

    versioned_name = config.name
    versioned_name = re.sub(r'[^\w]', '', versioned_name)
    versioned_name += "-" + config.version

    # Annoying fixups.
    config.name = config.name.replace("'", "\\'")
    config.icon_name = config.icon_name.replace("'", "\\'")

    if config.store not in [ "play", "none" ]:
        config.expansion = False

    # Figure out versions of the private and public data.
    private_version = str(time.time())

    if public_dir:
        public_version = private_version
    else:
        public_version = None

    # Render the various templates into control files.
    render(
        "AndroidManifest.tmpl.xml",
        "AndroidManifest.xml",
        config = config,
        manifest_extra = manifest_extra,
        )

    render(
        "strings.xml",
        "res/values/strings.xml",
        public_version = public_version,
        private_version = private_version,
        config = config)

    try:
        os.unlink(plat.path("build.xml"))
    except:
        pass

    iface.info("Updating source code.")

    edit_file("src/org/renpy/android/DownloaderActivity.java", r'import .*\.R;', 'import {}.R;'.format(config.package))

    iface.info("Updating build files.")

    # Update the project to a recent version.

    if os.path.exists(plat.path("project.properties")):
        os.unlink(plat.path("project.properties"))

    iface.call([plat.android, "update", "project",
        "-p", '.', '-t', plat.target, '-n', versioned_name,
        "--library", plat.path("android-sdk/extras/google/play_apk_expansion/downloader_library", relative=True),
        ])


    iface.info("Creating assets directory.")

    if os.path.isdir(plat.path("assets")):
        shutil.rmtree(plat.path("assets"))

    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)

    iface.background(make_assets)

    if config.expansion:
        iface.info("Creating expansion file.")
        expansion_file = "main.{}.{}.obb".format(config.numeric_version, config.package)

        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"))

        iface.background(make_expansion)

        # Write the file size into DownloaderActivity.
        file_size = os.path.getsize(plat.path(expansion_file))

    else:
        expansion_file = None
        file_size = 0

    # Write out constants.java.
    if not config.google_play_key:
        config.google_play_key = "NOT_SET"

    if not config.google_play_salt:
        config.google_play_salt = "1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20"

    render(
        "Constants.java",
        "src/org/renpy/android/Constants.java",
        config = config,
        file_size = file_size)


    iface.info("Packaging internal data.")

    private_dirs = [ 'private' ]

    if private_dir is not None:
        private_dirs.append(private_dir)

    if os.path.exists(plat.path("engine-private")):
        private_dirs.append(plat.path("engine-private"))

    def pack():
        make_tar(iface, plat.path("assets/private.mp3"), private_dirs)

    iface.background(pack)

    if public_dir is not None:
        iface.info("Packaging external data.")
        make_tar(iface, plat.path("assets/public.mp3"), [ public_dir ])

    # Copy over the icon files.
    copy_icon(directory, "icon.png", default_icon)

    # Copy the presplash files.
    copy_presplash(directory, "android-presplash", default_presplash)

    # Copy over the OUYA icon.
    ouya_icon = join_and_check(directory, "ouya-icon.png") or join_and_check(directory, "ouya_icon.png")

    if ouya_icon:
        if not os.path.exists(plat.path("res/drawable-xhdpi")):
            os.mkdir(plat.path("res/drawable-xhdpi"))

        shutil.copy(ouya_icon, plat.path("res/drawable-xhdpi/ouya_icon.png"))

    # Build.
    iface.info("I'm using Ant to build the package.")

    files = [ ]

    try:

        # Clean is required, so we don't use old code. (Not true anymore?)
        # iface.call([plat.ant, "clean" ] +  commands, cancel=True)
        iface.call([ plat.ant ] +  commands, cancel=True)

        files.append(plat.path("bin/" + versioned_name + "-release.apk"))

        if (expansion_file is not None) and ("install" in commands):
            iface.info("Uploading expansion file.")

            dest = "/mnt/sdcard/{}".format(expansion_file)

            iface.call([ plat.adb, "push", plat.path(expansion_file), dest ], cancel=True)

        if expansion_file is not None:
            plat.rename(plat.path(expansion_file), plat.path("bin/" + expansion_file))

            files.append(plat.path("bin/" + expansion_file))

    except subprocess.CalledProcessError:
        iface.fail("The build seems to have failed.")

    if launch:
        iface.info("Launching app.")

        if expansion_file:
            launch_activity = "DownloaderActivity"
        else:
            launch_activity = "PythonSDLActivity"

        iface.call([
            plat.adb, "shell",
            "am", "start",
            "-W",
            "-a", "android.intent.action.MAIN",
            "{}/org.renpy.android.{}".format(config.package, launch_activity),
            ], cancel=True)

    if finished is not None:
        finished(files)

    iface.final_success("The build seems to have succeeded.")
Example #10
0
def build(iface, directory, commands):

    # Are we doing a Ren'Py build?

    global RENPY
    RENPY = plat.renpy

    if not os.path.isdir(directory):
        iface.fail("{} is not a directory.".format(directory))

    if RENPY and not os.path.isdir(os.path.join(directory, "game")):
        iface.fail("{} does not contain a Ren'Py game.".format(directory))


    config = configure.Configuration(directory)
    if config.package is None:
        iface.fail("Run configure before attempting to build the app.")


    global blacklist
    global whitelist

    blacklist = PatternList("blacklist.txt")
    whitelist = PatternList("whitelist.txt")

    if RENPY:
        manifest_extra = None
        default_icon = plat.path("templates/renpy-icon.png")
        default_presplash = plat.path("templates/renpy-presplash.jpg")

        public_dir = None
        private_dir = None
        assets_dir = directory

    else:
        manifest_extra = ""
        default_icon = plat.path("templates/pygame-icon.png")
        default_presplash = plat.path("templates/pygame-presplash.jpg")

        if config.layout == "internal":
            private_dir = directory
            public_dir = None
            assets_dir = None
        elif config.layout == "external":
            private_dir = None
            public_dir = directory
            assets_dir = None
        elif config.layout == "split":
            private_dir = join_and_check(directory, "internal")
            public_dir = join_and_check(directory, "external")
            assets_dir = join_and_check(directory, "assets")

    versioned_name = config.name.replace(" ", "").replace("'", "") + "-" + config.version

    # Annoying fixups.
    config.name = config.name.replace("'", "\\'")
    config.icon_name = config.icon_name.replace("'", "\\'")

    # Figure out versions of the private and public data.
    private_version = str(time.time())

    if public_dir:
        public_version = private_version
    else:
        public_version = None

    # Render the various templates into control files.
    render(
        "AndroidManifest.tmpl.xml",
        "AndroidManifest.xml",
        config = config,
        manifest_extra = manifest_extra,
        )

    render(
        "strings.xml",
        "res/values/strings.xml",
        public_version = public_version,
        private_version = private_version,
        config = config)

    try:
        os.unlink(plat.path("build.xml"))
    except:
        pass

    iface.info("Updating source code.")

    edit_file("src/org/renpy/android/DownloaderActivity.java", r'import .*\.R;', 'import {}.R;'.format(config.package))

    iface.info("Updating build files.")

    # Update the project to a recent version.

    iface.call([plat.android, "update", "project", "-p", '.', '-t', 'android-8', '-n', versioned_name,
        # "--library", "android-sdk/extras/google/play_licensing/library",
        "--library", plat.path("android-sdk/extras/google/play_apk_expansion/downloader_library", relative=True),
        ])


    iface.info("Creating assets directory.")

    if os.path.isdir(plat.path("assets")):
        shutil.rmtree(plat.path("assets"))

    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)

    iface.background(make_assets)

    if config.expansion:
        iface.info("Creating expansion file.")
        expansion_file = "main.{}.{}.obb".format(config.numeric_version, config.package)

        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"))

        iface.background(make_expansion)

        # Write the file size into DownloaderActivity.
        file_size = os.path.getsize(plat.path(expansion_file))

        edit_file("src/org/renpy/android/DownloaderActivity.java",
            r'    private int fileVersion =',
            '    private int fileVersion = {};'.format(config.numeric_version))

        edit_file("src/org/renpy/android/DownloaderActivity.java",
            r'    private int fileSize =',
            '    private int fileSize = {};'.format(file_size))

    else:
        expansion_file = None

    # Update the GP key and salt.
    if config.google_play_key:
        edit_file("src/org/renpy/android/DownloaderService.java",
            r'    private static final String BASE64_PUBLIC_KEY',
            '    private static final String BASE64_PUBLIC_KEY = "%s";' % config.google_play_key)

    if config.google_play_salt:
        edit_file("src/org/renpy/android/DownloaderService.java",
            r'    private static final byte\[\] SALT',
            '    private static final byte[] SALT = new byte[] { %s };' % config.google_play_salt)


    iface.info("Packaging internal data.")

    private_dirs = [ 'private' ]

    if private_dir is not None:
        private_dirs.append(private_dir)

    if os.path.exists(plat.path("engine-private")):
        private_dirs.append(plat.path("engine-private"))

    def pack():
        make_tar(plat.path("assets/private.mp3"), private_dirs)

    iface.background(pack)

    if public_dir is not None:
        iface.info("Packaging external data.")
        make_tar(plat.path("assets/public.mp3"), [ public_dir ])

    # Copy over the icon and presplash files.
    copy_icon(directory, "icon.png", default_icon)
    copy_icon(directory, "presplash.jpg", default_presplash)

    # Copy over the OUYA icon.
    ouya_icon = join_and_check(directory, "ouya-icon.png") or join_and_check(directory, "ouya_icon.png")

    if ouya_icon:
        if not os.path.exists(plat.path("res/drawable-xhdpi")):
            os.mkdir(plat.path("res/drawable-xhdpi"))

        shutil.copy(ouya_icon, plat.path("res/drawable-xhdpi/ouya_icon.png"))

    # Build.
    iface.info("I'm using Ant to build the package.")

    try:

        # Clean is required, so we don't use old code.
        iface.call([plat.ant, "clean"] +  commands, cancel=True)

        if (expansion_file is not None) and ("install" in commands):
            iface.info("Uploading expansion file.")

            dest = "/mnt/sdcard/{}".format(expansion_file)

            iface.call([ plat.adb, "push", plat.path(expansion_file), dest ], cancel=True)

        if expansion_file is not None:
            plat.rename(plat.path(expansion_file), plat.path("bin/" + expansion_file))

    except subprocess.CalledProcessError:
        iface.fail("The build seems to have failed.")

    iface.final_success("The build seems to have succeeded.")