Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.x] Add GDNative libraries to Android custom Gradle builds #49912

Merged
merged 1 commit into from
Jun 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 67 additions & 1 deletion platform/android/export/export.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "export.h"

#include "core/io/image_loader.h"
#include "core/io/json.h"
#include "core/io/marshalls.h"
#include "core/io/zip_io.h"
#include "core/os/dir_access.h"
Expand Down Expand Up @@ -206,6 +207,7 @@ static const char *LEGACY_BUILD_SPLASH_IMAGE_EXPORT_PATH = "res/drawable-nodpi-v
static const char *SPLASH_BG_COLOR_PATH = "res/drawable-nodpi/splash_bg_color.png";
static const char *LEGACY_BUILD_SPLASH_BG_COLOR_PATH = "res/drawable-nodpi-v4/splash_bg_color.png";
static const char *SPLASH_CONFIG_PATH = "res://android/build/res/drawable/splash_drawable.xml";
static const char *GDNATIVE_LIBS_PATH = "res://android/build/libs/gdnativelibs.json";

const String SPLASH_CONFIG_XML_CONTENT = R"SPLASH(<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
Expand Down Expand Up @@ -277,6 +279,11 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
EditorProgress *ep;
};

struct CustomExportData {
bool debug;
Vector<String> libs;
};

Vector<PluginConfigAndroid> plugins;
String last_plugin_names;
uint64_t last_custom_build_time = 0;
Expand Down Expand Up @@ -761,6 +768,33 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
return OK;
}

static Error copy_gradle_so(void *p_userdata, const SharedObject &p_so) {
ERR_FAIL_COND_V_MSG(!p_so.path.get_file().begins_with("lib"), FAILED,
"Android .so file names must start with \"lib\", but got: " + p_so.path);
Vector<String> abis = get_abis();
CustomExportData *export_data = (CustomExportData *)p_userdata;
bool exported = false;
for (int i = 0; i < p_so.tags.size(); ++i) {
int abi_index = abis.find(p_so.tags[i]);
if (abi_index != -1) {
exported = true;
String base = "res://android/build/libs";
String type = export_data->debug ? "debug" : "release";
String abi = abis[abi_index];
String filename = p_so.path.get_file();
String dst_path = base.plus_file(type).plus_file(abi).plus_file(filename);
Vector<uint8_t> data = FileAccess::get_file_as_array(p_so.path);
print_verbose("Copying .so file from " + p_so.path + " to " + dst_path);
Error err = store_file_at_path(dst_path, data);
ERR_FAIL_COND_V_MSG(err, err, "Failed to copy .so file from " + p_so.path + " to " + dst_path);
export_data->libs.push_back(dst_path);
}
}
ERR_FAIL_COND_V_MSG(!exported, FAILED,
"Cannot determine ABI for library \"" + p_so.path + "\". One of the supported ABIs must be used as a tag: " + String(" ").join(abis));
return OK;
}

bool _has_storage_permission(const Vector<String> &p_permissions) {
return p_permissions.find("android.permission.READ_EXTERNAL_STORAGE") != -1 || p_permissions.find("android.permission.WRITE_EXTERNAL_STORAGE") != -1;
}
Expand Down Expand Up @@ -2744,6 +2778,30 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
}
}

void _remove_copied_libs() {
print_verbose("Removing previously installed libraries...");
Error error;
String libs_json = FileAccess::get_file_as_string(GDNATIVE_LIBS_PATH, &error);
if (error || libs_json.empty()) {
print_verbose("No previously installed libraries found");
return;
}

Variant result;
String error_string;
int error_line;
error = JSON::parse(libs_json, result, error_string, error_line);
ERR_FAIL_COND_MSG(error, "Error parsing \"" + libs_json + "\" on line " + itos(error_line) + ": " + error_string);

Vector<String> libs = result;
DirAccessRef da = DirAccess::create(DirAccess::ACCESS_RESOURCES);
for (int i = 0; i < libs.size(); i++) {
print_verbose("Removing previously installed library " + libs[i]);
da->remove(libs[i]);
}
da->remove(GDNATIVE_LIBS_PATH);
}

String join_list(List<String> parts, const String &separator) const {
String ret;
for (int i = 0; i < parts.size(); ++i) {
Expand Down Expand Up @@ -2855,13 +2913,21 @@ class EditorExportPlatformAndroid : public EditorExportPlatform {
_update_custom_build_project();
//stores all the project files inside the Gradle project directory. Also includes all ABIs
_clear_assets_directory();
_remove_copied_libs();
if (!apk_expansion) {
print_verbose("Exporting project files..");
err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, nullptr, ignore_so_file);
CustomExportData user_data;
user_data.debug = p_debug;
err = export_project_files(p_preset, rename_and_store_file_in_gradle_project, &user_data, copy_gradle_so);
if (err != OK) {
EditorNode::add_io_error("Could not export project files to gradle project\n");
return err;
}
if (user_data.libs.size() > 0) {
FileAccessRef fa = FileAccess::open(GDNATIVE_LIBS_PATH, FileAccess::WRITE);
fa->store_string(JSON::print(user_data.libs, "\t"));
fa->close();
}
} else {
print_verbose("Saving apk expansion file..");
err = save_apk_expansion_file(p_preset, p_path);
Expand Down
8 changes: 0 additions & 8 deletions platform/android/export/gradle_export_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,6 @@ Error create_directory(const String &p_dir) {
return OK;
}

// Implementation of EditorExportSaveSharedObject.
// This method will only be called as an input to export_project_files.
// This method lets the .so files for all ABIs to be copied
// into the gradle project from the .AAR file
Error ignore_so_file(void *p_userdata, const SharedObject &p_so) {
return OK;
}

// Writes p_data into a file at p_path, creating directories if necessary.
// Note: this will overwrite the file at p_path if it already exists.
Error store_file_at_path(const String &p_path, const Vector<uint8_t> &p_data) {
Expand Down