From 970bd6ed34555f662a62fa6ffb62c6422c814d34 Mon Sep 17 00:00:00 2001 From: Andrey Filipenkov Date: Sat, 25 Feb 2023 10:15:09 +0300 Subject: [PATCH] adjust project for Android (except AI) --- AI/CMakeLists.txt | 9 ++- CMakeLists.txt | 78 ++++++++++++++++--- Global.h | 2 +- android/GeneratedVersion.java.in | 2 +- android/vcmi-app/.gitignore | 7 ++ .../java/eu/vcmi/vcmi/VcmiSDLActivity.java | 2 +- .../java/eu/vcmi/vcmi/util/LibsLoader.java | 4 +- .../main/java/org/libsdl/app/SDLActivity.java | 9 +-- client/CMT.cpp | 4 +- client/CMakeLists.txt | 21 +++-- cmake_modules/VCMI_lib.cmake | 4 - conanfile.py | 7 ++ lib/CAndroidVMHelper.h | 2 +- lib/logging/CLogger.cpp | 2 +- lib/logging/CLogger.h | 2 +- server/CMakeLists.txt | 16 ++-- 16 files changed, 127 insertions(+), 44 deletions(-) diff --git a/AI/CMakeLists.txt b/AI/CMakeLists.txt index b396529d2..d866aea3f 100644 --- a/AI/CMakeLists.txt +++ b/AI/CMakeLists.txt @@ -31,6 +31,9 @@ if(NOT fuzzylite_FOUND) set(FL_BUILD_BINARY OFF CACHE BOOL "") set(FL_BUILD_SHARED OFF CACHE BOOL "") set(FL_BUILD_TESTS OFF CACHE BOOL "") + if(ANDROID) + set(FL_BACKTRACE OFF CACHE BOOL "" FORCE) + endif() #It is for compiling FuzzyLite, it will not compile without it on GCC if("x${CMAKE_CXX_COMPILER_FRONTEND_VARIANT}" STREQUAL "xGNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") add_compile_options(-Wno-error=deprecated-declarations) @@ -45,9 +48,11 @@ endif() ####################################### add_subdirectory(BattleAI) -add_subdirectory(StupidAI) -add_subdirectory(EmptyAI) add_subdirectory(VCAI) +if(NOT ANDROID) + add_subdirectory(StupidAI) + add_subdirectory(EmptyAI) +endif() if(ENABLE_NULLKILLER_AI) add_subdirectory(Nullkiller) endif() diff --git a/CMakeLists.txt b/CMakeLists.txt index 7d6ce9bd4..404f6d7d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,10 +41,15 @@ if(NOT CMAKE_BUILD_TYPE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release RelWithDebInfo) endif() +set(qtParts ON) +if(ANDROID) + set(qtParts OFF) +endif() + option(ENABLE_ERM "Enable compilation of ERM scripting module" OFF) option(ENABLE_LUA "Enable compilation of LUA scripting module" OFF) -option(ENABLE_LAUNCHER "Enable compilation of launcher" ON) -option(ENABLE_EDITOR "Enable compilation of map editor" ON) +option(ENABLE_LAUNCHER "Enable compilation of launcher" ${qtParts}) +option(ENABLE_EDITOR "Enable compilation of map editor" ${qtParts}) option(ENABLE_TRANSLATIONS "Enable generation of translations for launcher and editor" ON) option(ENABLE_NULLKILLER_AI "Enable compilation of Nullkiller AI library" ON) @@ -64,7 +69,7 @@ option(ENABLE_SINGLE_APP_BUILD "Builds client and server as single executable" O option(COPY_CONFIG_ON_BUILD "Copies config folder into output directory at building phase" ON) # Used for Snap packages and also useful for debugging -if(NOT APPLE_IOS) +if(NOT APPLE_IOS AND NOT ANDROID) option(ENABLE_MONOLITHIC_INSTALL "Install everything in single directory on Linux and Mac" OFF) endif() @@ -81,8 +86,8 @@ if(ENABLE_ERM AND NOT ENABLE_LUA) set(ENABLE_LUA ON) endif() -# We don't want to deploy assets into build directory for iOS build -if(APPLE_IOS AND COPY_CONFIG_ON_BUILD) +# We don't want to deploy assets into build directory for android/iOS build +if((APPLE_IOS OR ANDROID) AND COPY_CONFIG_ON_BUILD) set(COPY_CONFIG_ON_BUILD OFF) endif() @@ -95,6 +100,10 @@ set(CMAKE_MODULE_PATH ${CMAKE_HOME_DIRECTORY}/cmake_modules ${PROJECT_SOURCE_DIR include(VCMIUtils) include(VersionDefinition) +if(ANDROID) + set(VCMI_VERSION "${APP_SHORT_VERSION}") + configure_file("android/GeneratedVersion.java.in" "${CMAKE_SOURCE_DIR}/android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/GeneratedVersion.java" @ONLY) +endif() vcmi_print_important_variables() @@ -280,6 +289,15 @@ if(MINGW OR MSVC) endif(MINGW) endif(MINGW OR MSVC) +if(ANDROID) + if(ANDROID_NDK_MAJOR LESS 23 AND ANDROID_ABI MATCHES "^armeabi") + # libunwind must come before other shared libs: + # https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md#Unwinding + list(APPEND SYSTEM_LIBS unwind) + endif() + list(APPEND SYSTEM_LIBS log) +endif() + if(CMAKE_COMPILER_IS_GNUCXX OR NOT WIN32) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpointer-arith") @@ -447,6 +465,10 @@ elseif(APPLE) set(DATA_DIR ".") endif() endif() +elseif(ANDROID) + include(GNUInstallDirs) + set(LIB_DIR "jniLibs/${ANDROID_ABI}") + set(DATA_DIR "assets") else() # includes lib path which determines where to install shared libraries (either /lib or /lib64) include(GNUInstallDirs) @@ -482,8 +504,8 @@ else() endif() endif() -# iOS has flat libs directory structure -if(APPLE_IOS) +# iOS/Android have flat libs directory structure +if(APPLE_IOS OR ANDROID) set(AI_LIB_DIR "${LIB_DIR}") set(SCRIPTING_LIB_DIR "${LIB_DIR}") else() @@ -535,14 +557,48 @@ endif() # Installation section # ####################################### -install(DIRECTORY config DESTINATION ${DATA_DIR}) -install(DIRECTORY Mods DESTINATION ${DATA_DIR}) +if(ANDROID) + if(ANDROID_STL MATCHES "_shared$") + set(stlLibName "${CMAKE_SHARED_LIBRARY_PREFIX}${ANDROID_STL}${CMAKE_SHARED_LIBRARY_SUFFIX}") + install(FILES "${CMAKE_SYSROOT}/usr/lib/${ANDROID_SYSROOT_LIB_SUBDIR}/${stlLibName}" + DESTINATION ${LIB_DIR} + ) + endif() + + install(FILES AUTHORS + DESTINATION res/raw + RENAME authors.txt + ) + + # zip internal assets - 'config' and 'Mods' dirs, save md5 of the zip + install(CODE " + cmake_path(ABSOLUTE_PATH CMAKE_INSTALL_PREFIX + OUTPUT_VARIABLE absolute_install_prefix + ) + set(absolute_data_dir \"\${absolute_install_prefix}/${DATA_DIR}\") + file(MAKE_DIRECTORY \"\${absolute_data_dir}\") + + set(internal_data_zip \"\${absolute_data_dir}/internalData.zip\") + execute_process(COMMAND + \"${CMAKE_COMMAND}\" -E tar c \"\${internal_data_zip}\" --format=zip -- config Mods + WORKING_DIRECTORY \"${CMAKE_SOURCE_DIR}\" + ) + + file(MD5 \"\${internal_data_zip}\" internal_data_zip_md5) + file(WRITE \"\${absolute_data_dir}/internalDataHash.txt\" + \${internal_data_zip_md5} + ) + ") +else() + install(DIRECTORY config DESTINATION ${DATA_DIR}) + install(DIRECTORY Mods DESTINATION ${DATA_DIR}) +endif() if(ENABLE_LUA) install(DIRECTORY scripts DESTINATION ${DATA_DIR}) endif() -# that script is useless for Windows and iOS -if(NOT WIN32 AND NOT APPLE_IOS) +# that script is useless for Windows / iOS / Android +if(NOT WIN32 AND NOT APPLE_IOS AND NOT ANDROID) install(FILES vcmibuilder DESTINATION ${BIN_DIR} PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE GROUP_READ GROUP_EXECUTE diff --git a/Global.h b/Global.h index c8b4c1d21..c1ca57ff1 100644 --- a/Global.h +++ b/Global.h @@ -34,7 +34,7 @@ static_assert(sizeof(bool) == 1, "Bool needs to be 1 byte in size."); #elif defined(__linux__) || defined(__gnu_linux__) || defined(linux) || defined(__linux) # define VCMI_UNIX # define VCMI_XDG -# ifdef __ANDROID__ +# if defined(__ANDROID__) || defined(ANDROID) # define VCMI_ANDROID # endif #elif defined(__FreeBSD_kernel__) || defined(__FreeBSD__) diff --git a/android/GeneratedVersion.java.in b/android/GeneratedVersion.java.in index 609fa5523..0e8263573 100644 --- a/android/GeneratedVersion.java.in +++ b/android/GeneratedVersion.java.in @@ -1,7 +1,7 @@ package eu.vcmi.vcmi.util; /** - * Generated via cmake (./project/vcmi-app/cmake-scripts/versions.cmake) + * Generated via cmake */ public class GeneratedVersion { diff --git a/android/vcmi-app/.gitignore b/android/vcmi-app/.gitignore index 796b96d1c..6e0beb78f 100644 --- a/android/vcmi-app/.gitignore +++ b/android/vcmi-app/.gitignore @@ -1 +1,8 @@ /build + +# generated by CMake build +/src/main/assets/internalData.zip +/src/main/assets/internalDataHash.txt +/src/main/java/eu/vcmi/vcmi/util/GeneratedVersion.java +/src/main/jniLibs +/src/main/res/raw/authors.txt diff --git a/android/vcmi-app/src/main/java/eu/vcmi/vcmi/VcmiSDLActivity.java b/android/vcmi-app/src/main/java/eu/vcmi/vcmi/VcmiSDLActivity.java index 9c0fb3852..4d00f8991 100644 --- a/android/vcmi-app/src/main/java/eu/vcmi/vcmi/VcmiSDLActivity.java +++ b/android/vcmi-app/src/main/java/eu/vcmi/vcmi/VcmiSDLActivity.java @@ -80,7 +80,7 @@ public class VcmiSDLActivity extends SDLActivity @Override protected String getMainSharedObject() { - String library = "libvcmi-client.so"; + String library = "libvcmiclient.so"; return getContext().getApplicationInfo().nativeLibraryDir + "/" + library; } diff --git a/android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/LibsLoader.java b/android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/LibsLoader.java index 4d82af02c..615fb152e 100644 --- a/android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/LibsLoader.java +++ b/android/vcmi-app/src/main/java/eu/vcmi/vcmi/util/LibsLoader.java @@ -52,7 +52,7 @@ public final class LibsLoader public static void loadClientLibs(Context ctx) { loadCommon(); - loadLib("vcmi-client", false); + loadLib("vcmiclient", false); SDL.setContext(ctx); NativeMethods.clientSetupJNI(); NativeMethods.initClassloader(); @@ -61,7 +61,7 @@ public final class LibsLoader public static void loadServerLibs() { loadCommon(); - loadLib("vcmi-server", false); + loadLib("vcmiserver", false); NativeMethods.initClassloader(); } } diff --git a/android/vcmi-app/src/main/java/org/libsdl/app/SDLActivity.java b/android/vcmi-app/src/main/java/org/libsdl/app/SDLActivity.java index e8bfdf992..09ce4ab12 100644 --- a/android/vcmi-app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android/vcmi-app/src/main/java/org/libsdl/app/SDLActivity.java @@ -243,9 +243,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh * It can be overridden by derived classes. */ protected String getMainSharedObject() { - String library = "libvcmi-client.so"; - - return getContext().getApplicationInfo().nativeLibraryDir + "/" + library; + return null; } /** @@ -265,13 +263,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh * @return names of shared libraries to be loaded (e.g. "SDL2", "main"). */ protected String[] getLibraries() { + // SDL is linked statically, no need to load anything return new String[] { - "SDL2", + // "SDL2", // "SDL2_image", // "SDL2_mixer", // "SDL2_net", // "SDL2_ttf", - "main" + // "main" }; } diff --git a/client/CMT.cpp b/client/CMT.cpp index f85fd029c..ebdbaf825 100644 --- a/client/CMT.cpp +++ b/client/CMT.cpp @@ -57,7 +57,7 @@ #include #endif #ifdef VCMI_ANDROID -#include "lib/CAndroidVMHelper.h" +#include "../lib/CAndroidVMHelper.h" #endif #include "CMT.h" @@ -580,7 +580,7 @@ void playIntro() } } -#ifndef VCMI_IOS +#if !defined(VCMI_IOS) && !defined(VCMI_ANDROID) static bool checkVideoMode(int monitorIndex, int w, int h) { //we only check that our desired window size fits on screen diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 958cb297b..64f94d982 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -245,13 +245,16 @@ endif() assign_source_group(${client_SRCS} ${client_HEADERS} VCMI_client.rc) -if(ANDROID) # android needs client/server to be libraries, not executables, so we can't reuse the build part of this script - return() +if(ANDROID) + add_library(vcmiclient SHARED ${client_SRCS} ${client_HEADERS}) +else() + add_executable(vcmiclient ${client_SRCS} ${client_HEADERS}) endif() -add_executable(vcmiclient ${client_SRCS} ${client_HEADERS}) - -add_dependencies(vcmiclient vcmiserver BattleAI StupidAI VCAI) +add_dependencies(vcmiclient vcmiserver BattleAI VCAI) +if(NOT ANDROID) + add_dependencies(vcmiclient StupidAI) +endif() if(ENABLE_NULLKILLER_AI) add_dependencies(vcmiclient Nullkiller) endif() @@ -362,12 +365,18 @@ if(APPLE_IOS) WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) install(TARGETS vcmiclient DESTINATION Payload COMPONENT app) # for ipa generation with cpack +elseif(ANDROID) + vcmi_install_conan_deps("\${CMAKE_INSTALL_PREFIX}/${LIB_DIR}") + add_custom_command(TARGET vcmiclient POST_BUILD + COMMAND ${CMAKE_COMMAND} --install "${CMAKE_BINARY_DIR}" --config "$" --prefix "${CMAKE_SOURCE_DIR}/android/vcmi-app/src/main" + ) + install(TARGETS vcmiclient DESTINATION ${LIB_DIR}) else() install(TARGETS vcmiclient DESTINATION ${BIN_DIR}) endif() #install icons and desktop file on Linux -if(NOT WIN32 AND NOT APPLE) +if(NOT WIN32 AND NOT APPLE AND NOT ANDROID) #FIXME: move to client makefile? install(FILES "${CMAKE_SOURCE_DIR}/client/icons/vcmiclient.64x64.png" DESTINATION share/icons/hicolor/64x64/apps RENAME vcmiclient.png) install(FILES "${CMAKE_SOURCE_DIR}/client/icons/vcmiclient.48x48.png" DESTINATION share/icons/hicolor/48x48/apps RENAME vcmiclient.png) diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index 42fe2112f..e363833e1 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -488,10 +488,6 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ) endif() - if(ANDROID) - return() - endif() - vcmi_set_output_dir(${TARGET_NAME} "") enable_pch(${TARGET_NAME}) diff --git a/conanfile.py b/conanfile.py index d570f39ea..f93afed96 100644 --- a/conanfile.py +++ b/conanfile.py @@ -227,6 +227,13 @@ class VCMI(ConanFile): tc = CMakeToolchain(self) tc.variables["USING_CONAN"] = True tc.variables["CONAN_INSTALL_FOLDER"] = self.install_folder + if self.settings.os == "Android": + tc.variables["ANDROID_SYSROOT_LIB_SUBDIR"] = { + 'armv7': 'arm-linux-androideabi', + 'armv8': 'aarch64-linux-android', + 'x86': 'i686-linux-android', + 'x86_64': 'x86_64-linux-android', + }.get(str(self.settings.arch)) if cross_building(self) and self.settings.os == "Windows": tc.variables["CONAN_SYSTEM_LIBRARY_LOCATION"] = self.env["CONAN_SYSTEM_LIBRARY_LOCATION"] tc.generate() diff --git a/lib/CAndroidVMHelper.h b/lib/CAndroidVMHelper.h index b46272d48..9d77c2700 100644 --- a/lib/CAndroidVMHelper.h +++ b/lib/CAndroidVMHelper.h @@ -17,7 +17,7 @@ #include /// helper class that allows access to java vm to communicate with java code from native -class CAndroidVMHelper +class DLL_LINKAGE CAndroidVMHelper { JNIEnv * envPtr; bool detachInDestructor; diff --git a/lib/logging/CLogger.cpp b/lib/logging/CLogger.cpp index c892eecd2..1405f0623 100644 --- a/lib/logging/CLogger.cpp +++ b/lib/logging/CLogger.cpp @@ -348,7 +348,7 @@ EConsoleTextColor::EConsoleTextColor CColorMapping::getColorFor(const CLoggerDom } CLogConsoleTarget::CLogConsoleTarget(CConsoleHandler * console) : -#ifndef VCMI_IOS +#if !defined(VCMI_IOS) && !defined(VCMI_ANDROID) console(console), #endif threshold(ELogLevel::INFO), coloredOutputEnabled(true) diff --git a/lib/logging/CLogger.h b/lib/logging/CLogger.h index 1f602db51..4fa461efa 100644 --- a/lib/logging/CLogger.h +++ b/lib/logging/CLogger.h @@ -198,7 +198,7 @@ public: void write(const LogRecord & record) override; private: -#ifndef VCMI_IOS +#if !defined(VCMI_IOS) && !defined(VCMI_ANDROID) CConsoleHandler * console; #endif ELogLevel::ELogLevel threshold; diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 56379c69a..9eabe58fc 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -20,16 +20,16 @@ set(server_HEADERS assign_source_group(${server_SRCS} ${server_HEADERS}) -if(ANDROID) # android needs client/server to be libraries, not executables, so we can't reuse the build part of this script - return() -endif() - if(ENABLE_SINGLE_APP_BUILD) add_library(vcmiserver STATIC ${server_SRCS} ${server_HEADERS}) target_compile_definitions(vcmiserver PUBLIC VCMI_DLL_STATIC=1) set(server_LIBS vcmi_lib_server) else() - add_executable(vcmiserver ${server_SRCS} ${server_HEADERS}) + if(ANDROID) + add_library(vcmiserver SHARED ${server_SRCS} ${server_HEADERS}) + else() + add_executable(vcmiserver ${server_SRCS} ${server_HEADERS}) + endif() set(server_LIBS vcmi) endif() @@ -54,5 +54,9 @@ vcmi_set_output_dir(vcmiserver "") enable_pch(vcmiserver) if(NOT ENABLE_SINGLE_APP_BUILD) - install(TARGETS vcmiserver DESTINATION ${BIN_DIR}) + if(ANDROID) + install(TARGETS vcmiserver DESTINATION ${LIB_DIR}) + else() + install(TARGETS vcmiserver DESTINATION ${BIN_DIR}) + endif() endif()