Skip to content

Commit

Permalink
Added support for aab
Browse files Browse the repository at this point in the history
  • Loading branch information
misl6 committed Jul 17, 2021
1 parent a633193 commit 46dd7e8
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 64 deletions.
2 changes: 1 addition & 1 deletion pythonforandroid/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ def strip_libraries(self, arch):
if len(tokens) > 1:
strip = strip.bake(tokens[1:])

libs_dir = join(self.dist_dir, '_python_bundle',
libs_dir = join(self.dist_dir, f'_python_bundle__{arch.arch}',
'_python_bundle', 'modules')
filens = shprint(sh.find, libs_dir, join(self.dist_dir, 'libs'),
'-iname', '*.so', _env=env).stdout.decode('utf-8')
Expand Down
17 changes: 9 additions & 8 deletions pythonforandroid/bootstraps/common/build/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ def make_package(args):
# Package up the private data (public not supported).
use_setup_py = get_dist_info_for("use_setup_py",
error_if_missing=False) is True
tar_dirs = [env_vars_tarpath]
private_tar_dirs = [env_vars_tarpath]
_temp_dirs_to_clean = []
try:
if args.private:
Expand All @@ -277,7 +277,7 @@ def make_package(args):
):
print('No setup.py/pyproject.toml used, copying '
'full private data into .apk.')
tar_dirs.append(args.private)
private_tar_dirs.append(args.private)
else:
print("Copying main.py's ONLY, since other app data is "
"expected in site-packages.")
Expand Down Expand Up @@ -309,10 +309,7 @@ def make_package(args):
)

# Append directory with all main.py's to result apk paths:
tar_dirs.append(main_py_only_dir)
for python_bundle_dir in ('private', '_python_bundle'):
if exists(python_bundle_dir):
tar_dirs.append(python_bundle_dir)
private_tar_dirs.append(main_py_only_dir)
if get_bootstrap_name() == "webview":
for asset in listdir('webview_includes'):
shutil.copy(join('webview_includes', asset), join(assets_dir, asset))
Expand All @@ -326,8 +323,13 @@ def make_package(args):
shutil.copytree(realpath(asset_src), join(assets_dir, asset_dest))

if args.private or args.launcher:
for arch in get_dist_info_for("archs"):
libs_dir = f"libs/{arch}"
make_tar(
join(libs_dir, 'pybundle.so'), [f'_python_bundle__{arch}'], args.ignore_path,
optimize_python=args.optimize_python)
make_tar(
join(assets_dir, 'private.mp3'), tar_dirs, args.ignore_path,
join(assets_dir, 'private.tar'), private_tar_dirs, args.ignore_path,
optimize_python=args.optimize_python)
finally:
for directory in _temp_dirs_to_clean:
Expand Down Expand Up @@ -410,7 +412,6 @@ def make_package(args):
version_code = 0
if not args.numeric_version:
# Set version code in format (arch-minsdk-app_version)
arch = get_dist_info_for("archs")[0]
arch_dict = {"x86_64": "9", "arm64-v8a": "8", "armeabi-v7a": "7", "x86": "6"}
arch_code = arch_dict.get(arch, '1')
min_sdk = args.min_sdk_version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ protected static void recursiveDelete(File f) {
f.delete();
}

public static void unpackData(
public static void unpackAsset(
Context ctx,
final String resource,
File target,
Expand Down Expand Up @@ -170,7 +170,74 @@ public static void unpackData(
target.mkdirs();

AssetExtract ae = new AssetExtract(ctx);
if (!ae.extractTar(resource + ".mp3", target.getAbsolutePath())) {
if (!ae.extractTar(resource + ".tar", target.getAbsolutePath(), "private")) {
String msg = "Could not extract " + resource + " data.";
if (ctx instanceof Activity) {
toastError((Activity)ctx, msg);
} else {
Log.v(TAG, msg);
}
}

try {
// Write .nomedia.
new File(target, ".nomedia").createNewFile();

// Write version file.
FileOutputStream os = new FileOutputStream(diskVersionFn);
os.write(dataVersion.getBytes());
os.close();
} catch (Exception e) {
Log.w("python", e);
}
}
}

public static void unpackPyBundle(
Context ctx,
final String resource,
File target,
boolean cleanup_on_version_update) {

Log.v(TAG, "Unpacking " + resource + " " + target.getName());

// The version of data in memory and on disk.
String dataVersion = "p4aisawesome"; // FIXME: Assets method is not usable for fake .so files bundled as a library.
String diskVersion = null;

Log.v(TAG, "Data version is " + dataVersion);

// If no version, no unpacking is necessary.
if (dataVersion == null) {
return;
}

// Check the current disk version, if any.
String filesDir = target.getAbsolutePath();
String diskVersionFn = filesDir + "/" + resource + ".version";

// FIXME: Keeping that for later. Now it is surely failing.
try {
byte buf[] = new byte[64];
InputStream is = new FileInputStream(diskVersionFn);
int len = is.read(buf);
diskVersion = new String(buf, 0, len);
is.close();
} catch (Exception e) {
diskVersion = "";
}

// If the disk data is out of date, extract it and write the version file.
if (! dataVersion.equals(diskVersion)) {
Log.v(TAG, "Extracting " + resource + " assets.");

if (cleanup_on_version_update) {
recursiveDelete(target);
}
target.mkdirs();

AssetExtract ae = new AssetExtract(ctx);
if (!ae.extractTar(resource + ".so", target.getAbsolutePath(), "pybundle")) {
String msg = "Could not extract " + resource + " data.";
if (ctx instanceof Activity) {
toastError((Activity)ctx, msg);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.io.FileOutputStream;
import java.io.FileNotFoundException;
import java.io.File;
import java.io.FileInputStream;

import java.util.zip.GZIPInputStream;

Expand All @@ -28,15 +29,20 @@ public AssetExtract(Context context) {
mAssetManager = context.getAssets();
}

public boolean extractTar(String asset, String target) {
public boolean extractTar(String asset, String target, String method) {

byte buf[] = new byte[1024 * 1024];

InputStream assetStream = null;
TarInputStream tis = null;

try {
assetStream = mAssetManager.open(asset, AssetManager.ACCESS_STREAMING);
if(method == "private"){
assetStream = mAssetManager.open(asset, AssetManager.ACCESS_STREAMING);
} else if (method == "pybundle") {
assetStream = new FileInputStream(asset);
}

tis = new TarInputStream(new BufferedInputStream(new GZIPInputStream(new BufferedInputStream(assetStream, 8192)), 8192));
} catch (IOException e) {
Log.e("python", "opening up extract tar", e);
Expand Down
26 changes: 11 additions & 15 deletions pythonforandroid/bootstraps/sdl2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ class SDL2GradleBootstrap(Bootstrap):
def assemble_distribution(self):
info_main("# Creating Android project ({})".format(self.name))

arch = self.ctx.archs[0]

if len(self.ctx.archs) > 1:
raise ValueError("SDL2/gradle support only one arch")

info("Copying SDL2/gradle build for {}".format(arch))
info("Copying SDL2/gradle build")
shprint(sh.rm, "-rf", self.dist_dir)
shprint(sh.cp, "-r", self.build_dir, self.dist_dir)

Expand All @@ -33,23 +28,24 @@ def assemble_distribution(self):
with current_directory(self.dist_dir):
info("Copying Python distribution")

python_bundle_dir = join('_python_bundle', '_python_bundle')

self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
self.distribute_javaclasses(self.ctx.javaclass_dir,
dest_dir=join("src", "main", "java"))

ensure_dir(python_bundle_dir)
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
for arch in self.ctx.archs:
python_bundle_dir = join(f'_python_bundle__{arch.arch}', '_python_bundle')
ensure_dir(python_bundle_dir)

self.distribute_libs(arch, [self.ctx.get_libs_dir(arch.arch)])
site_packages_dir = self.ctx.python_recipe.create_python_bundle(
join(self.dist_dir, python_bundle_dir), arch)
if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)

if 'sqlite3' not in self.ctx.recipe_build_order:
with open('blacklist.txt', 'a') as fileh:
fileh.write('\nsqlite3/*\nlib-dynload/_sqlite3.so\n')

if not self.ctx.with_debug_symbols:
self.strip_libraries(arch)
self.fry_eggs(site_packages_dir)
super().assemble_distribution()


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ private class UnpackFilesTask extends AsyncTask<String, Void, String> {
protected String doInBackground(String... params) {
File app_root_file = new File(params[0]);
Log.v(TAG, "Ready to unpack");
PythonUtil.unpackData(mActivity, "private", app_root_file, true);
PythonUtil.unpackAsset(mActivity, "private", app_root_file, true);
PythonUtil.unpackPyBundle(mActivity, getApplicationInfo().nativeLibraryDir + "/" + "pybundle", app_root_file, false);
return null;
}

Expand Down
26 changes: 1 addition & 25 deletions pythonforandroid/distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,7 @@ def get_distribution(
dist.name = name
dist.dist_dir = join(
ctx.dist_dir,
generate_dist_folder_name(
name,
[arch_name] if arch_name is not None else None,
)
)
name)
dist.recipes = recipes
dist.ndk_api = ctx.ndk_api
dist.archs = [arch_name]
Expand Down Expand Up @@ -265,23 +261,3 @@ def pretty_log_dists(dists, log_func=info):

for line in infos:
log_func('\t' + line)


def generate_dist_folder_name(base_dist_name, arch_names=None):
"""Generate the distribution folder name to use, based on a
combination of the input arguments.
Parameters
----------
base_dist_name : str
The core distribution identifier string
arch_names : list of str
The architecture compile targets
"""
if arch_names is None:
arch_names = ["no_arch_specified"]

return '{}__{}'.format(
base_dist_name,
'_'.join(arch_names)
)
33 changes: 23 additions & 10 deletions pythonforandroid/toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,6 @@ def check_python_dependencies():
toolchain_dir = dirname(__file__)
sys.path.insert(0, join(toolchain_dir, "tools", "external"))

APK_SUFFIX = '.apk'


def add_boolean_option(parser, names, no_names=None,
default=True, dest=None, description=None):
Expand Down Expand Up @@ -313,8 +311,8 @@ def __init__(self):
'(default: {})'.format(default_storage_dir)))

generic_parser.add_argument(
'--arch', help='The arch to build for.',
default='armeabi-v7a')
'--arch', help='The archs to build for.',
action='append', default=[])

# Options for specifying the Distribution
generic_parser.add_argument(
Expand Down Expand Up @@ -563,6 +561,11 @@ def add_parser(subparsers, *args, **kwargs):
'apk', help='Build an APK',
parents=[parser_packaging])

add_parser(
subparsers,
'aab', help='Build an AAB',
parents=[parser_packaging])

add_parser(
subparsers,
'create', help='Compile a set of requirements into a dist',
Expand Down Expand Up @@ -712,7 +715,7 @@ def add_parser(subparsers, *args, **kwargs):
self.ctx.symlink_bootstrap_files = args.symlink_bootstrap_files
self.ctx.java_build_tool = args.java_build_tool

self._archs = split_argument_list(args.arch)
self._archs = args.arch

self.ctx.local_recipes = args.local_recipes
self.ctx.copy_libs = args.copy_libs
Expand Down Expand Up @@ -1028,7 +1031,7 @@ def _build_package(self, args, package_type):
"""
Creates an android package using gradle
:param args: parser args
:param package_type: one of 'apk', 'aar'
:param package_type: one of 'apk', 'aar', 'aab'
:return (gradle output, build_args)
"""
ctx = self.ctx
Expand Down Expand Up @@ -1078,7 +1081,10 @@ def _build_package(self, args, package_type):
if args.build_mode == "debug":
gradle_task = "assembleDebug"
elif args.build_mode == "release":
gradle_task = "assembleRelease"
if package_type == "apk":
gradle_task = "assembleRelease"
elif package_type == "aab":
gradle_task = "bundleRelease"
else:
raise BuildInterruptingException(
"Unknown build mode {} for apk()".format(args.build_mode))
Expand All @@ -1092,7 +1098,7 @@ def _finish_package(self, args, output, build_args, package_type, output_dir):
:param args: the parser args
:param output: RunningCommand output
:param build_args: build args as returned by build.parse_args
:param package_type: one of 'apk', 'aar'
:param package_type: one of 'apk', 'aar', 'aab'
:param output_dir: where to put the package file
"""

Expand Down Expand Up @@ -1129,11 +1135,12 @@ def _finish_package(self, args, output, build_args, package_type, output_dir):
raise BuildInterruptingException('Couldn\'t find the built APK')

info_main('# Found android package file: {}'.format(package_file))
package_extension = f".{package_type}"
if package_add_version:
info('# Add version number to android package')
package_name = basename(package_file)[:-len(APK_SUFFIX)]
package_name = basename(package_file)[:-len(package_extension)]
package_file_dest = "{}-{}-{}".format(
package_name, build_args.version, APK_SUFFIX)
package_name, build_args.version, package_extension)
info('# Android package renamed to {}'.format(package_file_dest))
shprint(sh.cp, package_file, package_file_dest)
else:
Expand All @@ -1151,6 +1158,12 @@ def aar(self, args):
output_dir = join(self._dist.dist_dir, "build", "outputs", 'aar')
self._finish_package(args, output, build_args, 'aar', output_dir)

@require_prebuilt_dist
def aab(self, args):
output, build_args = self._build_package(args, package_type='aab')
output_dir = join(self._dist.dist_dir, "build", "outputs", 'bundle', args.build_mode)
self._finish_package(args, output, build_args, 'aab', output_dir)

@require_prebuilt_dist
def create(self, args):
"""Create a distribution directory if it doesn't already exist, run
Expand Down

0 comments on commit 46dd7e8

Please sign in to comment.