From e02b2a7b9aaeae0783d4217790c5bcf9d37abc04 Mon Sep 17 00:00:00 2001 From: Andrew Kaster Date: Wed, 19 Jul 2023 10:27:16 -0600 Subject: [PATCH] Ladybird: Make Android build work again, and tidy up files We don't need the extra gradle files in our sources, the Qt CMake integration will generate suitable ones for us. Make sure that assets is always a folder, so that we can get the proper layout for the ladybird-assets.tar.gz and CMake doesn't create a gzip file with the name "assets". Fix up the AndroidPlatform file and make sure it's linked into all the applications that need it. Also make sure to copy all the application shared libraries into the ladybird APK so that when we make them into proper Services, the libs are already there. --- Ladybird/AndroidPlatform.cpp | 58 ++++++++++---------- Ladybird/CMakeLists.txt | 7 +-- Ladybird/WebContent/CMakeLists.txt | 3 ++ Ladybird/WebDriver/CMakeLists.txt | 3 ++ Ladybird/android/AndroidManifest.xml | 3 -- Ladybird/android/assets/.gitkeep | 0 Ladybird/android/build.gradle | 81 ---------------------------- Ladybird/android/gradle.properties | 14 ----- Ladybird/cmake/AndroidExtras.cmake | 18 +++++-- Ladybird/cmake/InstallRules.cmake | 8 ++- 10 files changed, 58 insertions(+), 137 deletions(-) create mode 100644 Ladybird/android/assets/.gitkeep delete mode 100644 Ladybird/android/build.gradle delete mode 100644 Ladybird/android/gradle.properties diff --git a/Ladybird/AndroidPlatform.cpp b/Ladybird/AndroidPlatform.cpp index 436e51766e..f239f5a91e 100644 --- a/Ladybird/AndroidPlatform.cpp +++ b/Ladybird/AndroidPlatform.cpp @@ -10,9 +10,10 @@ #include #include #include +#include #include -#include #include +#include #include #include @@ -31,7 +32,7 @@ extern DeprecatedString s_serenity_resource_root; void android_platform_init(); static void extract_ladybird_resources(); -static ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedString output_directory); +static ErrorOr extract_tar_archive(String archive_file, DeprecatedString output_directory); void android_platform_init() { @@ -53,31 +54,25 @@ void extract_ladybird_resources() if (file_or_error.is_error()) { qDebug() << "Unable to open test file file as expected, extracting asssets..."; - MUST(extract_tar_archive(DeprecatedString::formatted("{}/ladybird-assets.tar", s_serenity_resource_root), s_serenity_resource_root)); + MUST(extract_tar_archive(MUST(String::formatted("{}/ladybird-assets.tar", s_serenity_resource_root)), s_serenity_resource_root)); } else { qDebug() << "Opened app-browser.png test file, good to go!"; qDebug() << "Hopefully no developer changed the asset files and expected them to be re-extracted!"; } } -ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedString output_directory) +ErrorOr extract_tar_archive(String archive_file, DeprecatedString output_directory) { constexpr size_t buffer_size = 4096; - auto file = TRY(Core::DeprecatedFile::open(archive_file, Core::OpenMode::ReadOnly)); + auto file = TRY(Core::InputBufferedFile::create(TRY(Core::File::open(archive_file, Core::File::OpenMode::Read)))); DeprecatedString old_pwd = TRY(Core::System::getcwd()); TRY(Core::System::chdir(output_directory)); ScopeGuard go_back = [&old_pwd] { MUST(Core::System::chdir(old_pwd)); }; - Core::InputFileStream file_stream(file); - - Archive::TarInputStream tar_stream(file_stream); - if (!tar_stream.valid()) { - qDebug() << "the provided file is not a well-formatted ustar file"; - return Error::from_errno(EINVAL); - } + auto tar_stream = TRY(Archive::TarInputStream::construct(make(move(file)))); HashMap global_overrides; HashMap local_overrides; @@ -96,14 +91,14 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin return {}; }; - for (; !tar_stream.finished(); tar_stream.advance()) { - Archive::TarFileHeader const& header = tar_stream.header(); + while (!tar_stream->finished()) { + Archive::TarFileHeader const& header = tar_stream->header(); // Handle meta-entries earlier to avoid consuming the file content stream. if (header.content_is_like_extended_header()) { switch (header.type_flag()) { case Archive::TarFileType::GlobalExtendedHeader: { - TRY(tar_stream.for_each_extended_header([&](StringView key, StringView value) { + TRY(tar_stream->for_each_extended_header([&](StringView key, StringView value) { if (value.length() == 0) global_overrides.remove(key); else @@ -112,7 +107,7 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin break; } case Archive::TarFileType::ExtendedHeader: { - TRY(tar_stream.for_each_extended_header([&](StringView key, StringView value) { + TRY(tar_stream->for_each_extended_header([&](StringView key, StringView value) { local_overrides.set(key, value); })); break; @@ -122,10 +117,11 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin VERIFY_NOT_REACHED(); } + TRY(tar_stream->advance()); continue; } - Archive::TarFileStream file_stream = tar_stream.file_contents(); + Archive::TarFileStream file_stream = tar_stream->file_contents(); // Handle other header types that don't just have an effect on extraction. switch (header.type_flag()) { @@ -133,12 +129,14 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin StringBuilder long_name; Array buffer; - size_t bytes_read; - while ((bytes_read = file_stream.read(buffer)) > 0) - long_name.append(reinterpret_cast(buffer.data()), bytes_read); + while (!file_stream.is_eof()) { + auto slice = TRY(file_stream.read_some(buffer)); + long_name.append(reinterpret_cast(slice.data()), slice.size()); + } local_overrides.set("path", long_name.to_deprecated_string()); + TRY(tar_stream->advance()); continue; } default: @@ -151,20 +149,22 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin path = path.prepend(header.prefix()); DeprecatedString filename = get_override("path"sv).value_or(path.string()); - DeprecatedString absolute_path = Core::DeprecatedFile::absolute_path(filename); + DeprecatedString absolute_path = TRY(FileSystem::absolute_path(filename)).to_deprecated_string(); auto parent_path = LexicalPath(absolute_path).parent(); + auto header_mode = TRY(header.mode()); switch (header.type_flag()) { case Archive::TarFileType::NormalFile: case Archive::TarFileType::AlternateNormalFile: { MUST(Core::Directory::create(parent_path, Core::Directory::CreateDirectories::Yes)); - int fd = TRY(Core::System::open(absolute_path, O_CREAT | O_WRONLY, header.mode())); + int fd = TRY(Core::System::open(absolute_path, O_CREAT | O_WRONLY, header_mode)); Array buffer; - size_t bytes_read; - while ((bytes_read = file_stream.read(buffer)) > 0) - TRY(Core::System::write(fd, buffer.span().slice(0, bytes_read))); + while (!file_stream.is_eof()) { + auto slice = TRY(file_stream.read_some(buffer)); + TRY(Core::System::write(fd, slice)); + } TRY(Core::System::close(fd)); break; @@ -178,9 +178,9 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin case Archive::TarFileType::Directory: { MUST(Core::Directory::create(parent_path, Core::Directory::CreateDirectories::Yes)); - auto result_or_error = Core::System::mkdir(absolute_path, header.mode()); + auto result_or_error = Core::System::mkdir(absolute_path, header_mode); if (result_or_error.is_error() && result_or_error.error().code() != EEXIST) - return result_or_error.error(); + return result_or_error.release_error(); break; } default: @@ -191,8 +191,8 @@ ErrorOr extract_tar_archive(DeprecatedString archive_file, DeprecatedStrin // Non-global headers should be cleared after every file. local_overrides.clear(); - } - file_stream.close(); + TRY(tar_stream->advance()); + } return {}; } diff --git a/Ladybird/CMakeLists.txt b/Ladybird/CMakeLists.txt index edf618dfeb..327cc5d83c 100644 --- a/Ladybird/CMakeLists.txt +++ b/Ladybird/CMakeLists.txt @@ -97,9 +97,7 @@ set(SOURCES main.cpp ) -qt_add_executable(ladybird ${SOURCES} - MANUAL_FINALIZATION -) +qt_add_executable(ladybird ${SOURCES}) target_link_libraries(ladybird PRIVATE Qt::Core Qt::Gui Qt::Network Qt::Widgets LibCore LibFileSystem LibGfx LibGUI LibIPC LibJS LibMain LibWeb LibWebView LibSQL) target_include_directories(ladybird PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) @@ -128,6 +126,7 @@ set_target_properties(ladybird PROPERTIES if (ANDROID) include(cmake/AndroidExtras.cmake) + link_android_libs(headless-browser) endif() add_custom_target(run${LADYBIRD_CUSTOM_TARGET_SUFFIX} @@ -141,8 +140,6 @@ add_custom_target(debug${LADYBIRD_CUSTOM_TARGET_SUFFIX} USES_TERMINAL ) -qt_finalize_executable(ladybird) - add_subdirectory(SQLServer) add_subdirectory(WebContent) add_subdirectory(WebDriver) diff --git a/Ladybird/WebContent/CMakeLists.txt b/Ladybird/WebContent/CMakeLists.txt index 93204007dc..29d78b67d5 100644 --- a/Ladybird/WebContent/CMakeLists.txt +++ b/Ladybird/WebContent/CMakeLists.txt @@ -28,3 +28,6 @@ qt_add_executable(WebContent ${WEBCONTENT_SOURCES}) target_include_directories(WebContent PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services/) target_include_directories(WebContent PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/..) target_link_libraries(WebContent PRIVATE Qt::Core Qt::Gui Qt::Network Qt::Multimedia LibAudio LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket) +if (ANDROID) + link_android_libs(WebContent) +endif() diff --git a/Ladybird/WebDriver/CMakeLists.txt b/Ladybird/WebDriver/CMakeLists.txt index 72dcd2e547..11f36a1bbc 100644 --- a/Ladybird/WebDriver/CMakeLists.txt +++ b/Ladybird/WebDriver/CMakeLists.txt @@ -17,3 +17,6 @@ target_include_directories(WebDriver PRIVATE ${SERENITY_SOURCE_DIR}/Userland) target_include_directories(WebDriver PRIVATE ${SERENITY_SOURCE_DIR}/Userland/Services) target_link_libraries(WebDriver PRIVATE Qt::Core Qt::Network LibCore LibFileSystem LibGfx LibIPC LibJS LibMain LibWeb LibWebSocket) add_dependencies(WebDriver headless-browser) +if (ANDROID) + link_android_libs(WebDriver) +endif() diff --git a/Ladybird/android/AndroidManifest.xml b/Ladybird/android/AndroidManifest.xml index d128be4f66..bddd787bd5 100644 --- a/Ladybird/android/AndroidManifest.xml +++ b/Ladybird/android/AndroidManifest.xml @@ -14,8 +14,5 @@ - - - diff --git a/Ladybird/android/assets/.gitkeep b/Ladybird/android/assets/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/Ladybird/android/build.gradle b/Ladybird/android/build.gradle deleted file mode 100644 index 4c711790f8..0000000000 --- a/Ladybird/android/build.gradle +++ /dev/null @@ -1,81 +0,0 @@ -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:7.0.2' - } -} - -repositories { - google() - mavenCentral() -} - -apply plugin: 'com.android.application' - -dependencies { - implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) -} - -android { - /******************************************************* - * The following variables: - * - androidBuildToolsVersion, - * - androidCompileSdkVersion - * - qtAndroidDir - holds the path to qt android files - * needed to build any Qt application - * on Android. - * - * are defined in gradle.properties file. This file is - * updated by QtCreator and androiddeployqt tools. - * Changing them manually might break the compilation! - *******************************************************/ - - compileSdkVersion androidCompileSdkVersion.toInteger() - buildToolsVersion androidBuildToolsVersion - ndkVersion androidNdkVersion - - // Extract native libraries from the APK - packagingOptions.jniLibs.useLegacyPackaging true - - sourceSets { - main { - manifest.srcFile 'AndroidManifest.xml' - java.srcDirs = [qtAndroidDir + '/src', 'src', 'java'] - aidl.srcDirs = [qtAndroidDir + '/src', 'src', 'aidl'] - res.srcDirs = [qtAndroidDir + '/res', 'res'] - resources.srcDirs = ['resources'] - renderscript.srcDirs = ['src'] - assets.srcDirs = ['assets'] - jniLibs.srcDirs = ['libs'] - } - } - - tasks.withType(JavaCompile) { - options.incremental = true - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - - lintOptions { - abortOnError false - } - - // Do not compress Qt binary resources file - aaptOptions { - noCompress 'rcc' - } - - defaultConfig { - resConfig "en" - minSdkVersion qtMinSdkVersion - targetSdkVersion qtTargetSdkVersion - ndk.abiFilters = qtTargetAbiList.split(",") - } -} diff --git a/Ladybird/android/gradle.properties b/Ladybird/android/gradle.properties deleted file mode 100644 index 263d70238a..0000000000 --- a/Ladybird/android/gradle.properties +++ /dev/null @@ -1,14 +0,0 @@ -# Project-wide Gradle settings. -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2500m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# Enable building projects in parallel -org.gradle.parallel=true - -# Gradle caching allows reusing the build artifacts from a previous -# build with the same inputs. However, over time, the cache size will -# grow. Uncomment the following line to enable it. -#org.gradle.caching=true diff --git a/Ladybird/cmake/AndroidExtras.cmake b/Ladybird/cmake/AndroidExtras.cmake index c1f39e7342..24e7f81b77 100644 --- a/Ladybird/cmake/AndroidExtras.cmake +++ b/Ladybird/cmake/AndroidExtras.cmake @@ -13,8 +13,12 @@ set_property(TARGET ladybird APPEND PROPERTY # # Android-specific sources and libs # -target_sources(ladybird PRIVATE AndroidPlatform.cpp) -target_link_libraries(ladybird PRIVATE LibCompress LibArchive) +add_library(android_init STATIC AndroidPlatform.cpp) +target_link_libraries(android_init PUBLIC Qt::Core Qt::Gui Qt::Network LibCompress LibArchive LibFileSystem) + +macro(link_android_libs target) + target_link_libraries(${target} PRIVATE android_init) +endmacro() # # NDK and Qt don't ship OpenSSL for Android @@ -27,7 +31,13 @@ FetchContent_Declare(android_openssl GIT_SHALLOW TRUE ) FetchContent_MakeAvailable(android_openssl) -set_property(TARGET ladybird APPEND PROPERTY QT_ANDROID_EXTRA_LIBS ${ANDROID_EXTRA_LIBS}) +link_android_libs(ladybird) +target_link_libraries(ladybird PRIVATE Qt::Network) +set_property(TARGET ladybird APPEND PROPERTY QT_ANDROID_EXTRA_LIBS ${ANDROID_EXTRA_LIBS} + "${CMAKE_CURRENT_BINARY_DIR}/WebContent/libWebContent_${ANDROID_ABI}.so" + "${CMAKE_CURRENT_BINARY_DIR}/SQLServer/libSQLServer_${ANDROID_ABI}.so" + "${CMAKE_CURRENT_BINARY_DIR}/WebDriver/libWebDriver_${ANDROID_ABI}.so" +) # # Copy resources into tarball for inclusion in /assets of APK @@ -60,6 +70,6 @@ add_custom_target(copy-content-filters "asset-bundle/res/ladybird/BrowserContentFilters.txt" ) add_dependencies(archive-assets copy-autoplay-allowlist copy-content-filters) -add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.tar.gz "${CMAKE_SOURCE_DIR}/android/assets") +add_custom_target(copy-assets COMMAND ${CMAKE_COMMAND} -E copy_if_different ladybird-assets.tar.gz "${CMAKE_SOURCE_DIR}/android/assets/") add_dependencies(copy-assets archive-assets) add_dependencies(ladybird copy-assets) diff --git a/Ladybird/cmake/InstallRules.cmake b/Ladybird/cmake/InstallRules.cmake index ea134c82ad..6ed7f2bef3 100644 --- a/Ladybird/cmake/InstallRules.cmake +++ b/Ladybird/cmake/InstallRules.cmake @@ -6,7 +6,13 @@ set(package ladybird) set(ladybird_applications ladybird SQLServer WebContent WebDriver headless-browser) -install(TARGETS ${ladybird_applications} +set(app_install_targets ${ladybird_applications}) +if (ANDROID) + # androiddeployqt will get confused with duplicate resources if we install every app + set(app_install_targets ladybird) +endif() + +install(TARGETS ${app_install_targets} EXPORT ladybirdTargets RUNTIME COMPONENT ladybird_Runtime