Android: Updated the toolchain file and CMake scripts

* Replaced the toolchain file with a new version based on [zuhowei's fork](https://github.com/zhuowei/android-cmake), which enables x64 builds as well as support for the latest NDK. This breaks compatibility with old build directories.
* Removed the STL dependency from **sfml-activity** rather than relying on *some* implementation implicitly linked by default.
* Deleted *project.properties*, which wasn't supposed to be part of the repository code. You have to use the Android SDK to recreate it (`android update project --path to/your/example --target 1 --name SFML-Example`).
* Made it possible to select a STL implementation to be used (default: `c++_shared`). Keep in mind that not all available configurations are necessarily compatible with SFML.
* Fixed linker flags to be compatible with Nvidia's Nsight Tegra for Visual Studio.
* It is now possible to compile the Android version using Nvidia's Nsight Tegra for Visual Studio (requires up-to-date CMake and `CMAKE_SFML_SYSTEM` to be set to `Android`; keep in mind that this is still experimental and requires further CMake updates).
* Updated and renamed some Android specific CMake variables.
* Made `armeabi-v7a` the default ABI for Android builds.
This commit is contained in:
Mario Liebisch 2015-01-30 15:37:06 +01:00 committed by Lukas Dürrenberger
parent 1de7644277
commit 34692d5a39
11 changed files with 1307 additions and 677 deletions

1
.gitattributes vendored
View File

@ -1,6 +1,7 @@
* text=auto eol=lf
extlibs/**/* -text -eol linguist-vendored
cmake/toolchains/android.toolchain.cmake -text -eol
*.png -text -eol
*.jpg -text -eol

View File

@ -8,10 +8,29 @@ macro(sfml_set_option var default type docstring)
set(${var} ${${var}} CACHE ${type} ${docstring} FORCE)
endmacro()
# set a default build type if none was provided
# this has to be done before the project() instruction!
# these options have to be set before CMake detects/configures the toolchain
# determine whether to create a debug or release build
sfml_set_option(CMAKE_BUILD_TYPE Release STRING "Choose the type of build (Debug or Release)")
# set Android specific options
# define the minimum API level to be used
sfml_set_option(ANDROID_API_MIN 9 STRING "Choose the Android API level to be used (minimum 9)")
# mirror the setting for the toolchain file
set(ANDROID_NATIVE_API_LEVEL ${ANDROID_API_MIN})
# define the path to the Android NDK
sfml_set_option(ANDROID_NDK "$ENV{ANDROID_NDK}" PATH "Path to the Android NDK")
# define the STL implementation to be used
sfml_set_option(ANDROID_STL c++_shared STRING "Choose the STL implementation to be used (experimental)")
# default the ABI to ARM v7a for hardware floating point
if(NOT ANDROID_ABI)
set(ANDROID_ABI armeabi-v7a)
endif()
# project name
project(SFML)
@ -64,24 +83,41 @@ endif()
# Android options
if(SFML_OS_ANDROID)
# force usage of the STL port
set(ANDROID_USE_STLPORT TRUE)
# make sure there's the android library available
if (${ANDROID_NATIVE_API_LEVEL} LESS 9)
message(FATAL_ERROR "API level must be equal or greater than 9")
if (${ANDROID_API_MIN} LESS 9)
message(FATAL_ERROR "Android API level must be equal or greater than 9. Please adjust the CMake variable 'ANDROID_API_MIN'.")
endif()
if(NOT ANDROID_NDK)
message(FATAL_ERROR "The Android NDK couldn't be found. Please adjust the CMake variable 'ANDROID_NDK' to point to the NDK directory.")
endif()
# CMake doesn't support defining the STL to be used with Nsight Tegra, so warn the user
if(CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")
message(WARNING "CMake might not properly support setting the STL. Make sure to adjust all generated library projects!")
endif()
# install everything in $NDK/sources/ because this path is appended by the NDK (convenient)
set(CMAKE_INSTALL_PREFIX ${ANDROID_NDK}/sources/sfml)
# we install libs in a subdirectory named after the ABI (lib/mips/*.so)
set(LIB_SUFFIX "/${ANDROID_ABI}")
# this is a workaround to compile sfml-activity without stlport_shared as dependency
# pass shared STL configuration (if any)
if (ANDROID_STL MATCHES "_shared")
add_definitions("-DSTL_LIBRARY=${ANDROID_STL}")
endif()
# this is a workaround to compile sfml-activity without the stl library as a dependency
# we save the original compilation command line to restore it later in Macro.cmake
set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STLPORT ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STLPORT "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STL ${CMAKE_CXX_CREATE_SHARED_LIBRARY})
set(CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STL "<CMAKE_CXX_COMPILER> <CMAKE_SHARED_LIBRARY_CXX_FLAGS> <LANGUAGE_COMPILE_FLAGS> <LINK_FLAGS> <CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS> <SONAME_FLAG><TARGET_SONAME> -o <TARGET> <OBJECTS> <LINK_LIBRARIES>")
else()
unset(ANDROID_ABI CACHE)
unset(ANDROID_API_MIN CACHE)
unset(ANDROID_STL CACHE)
unset(ANDROID_NATIVE_API_LEVEL CACHE)
unset(ANDROID_NDK CACHE)
endif()
# define SFML_STATIC if the build type is not set to 'shared'

View File

@ -60,7 +60,7 @@ elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
endif()
endif()
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Android")
set(SFML_OS_ANDROID 1)
set(SFML_OS_ANDROID 1)
# use the OpenGL ES implementation on Android
set(OPENGL_ES 1)

View File

@ -98,9 +98,9 @@ macro(sfml_add_library target)
if (${target} MATCHES "sfml-activity")
set_target_properties(${target} PROPERTIES COMPILE_FLAGS -fpermissive)
set_target_properties(${target} PROPERTIES LINK_FLAGS "-landroid -llog")
set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STLPORT})
set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITHOUT_STL})
else()
set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STLPORT})
set(CMAKE_CXX_CREATE_SHARED_LIBRARY ${CMAKE_CXX_CREATE_SHARED_LIBRARY_WITH_STL})
endif()
endif()
@ -176,3 +176,28 @@ macro(sfml_add_example target)
endif()
endmacro()
# macro to find packages on the host OS
# this is the same as in the toolchain file, which is here for Nsight Tegra VS
# since it won't use the Android toolchain file
if(CMAKE_VS_PLATFORM_NAME STREQUAL "Tegra-Android")
macro(find_host_package)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER)
if(CMAKE_HOST_WIN32)
set(WIN32 1)
set(UNIX)
elseif(CMAKE_HOST_APPLE)
set(APPLE 1)
set(UNIX)
endif()
find_package(${ARGN})
set(WIN32)
set(APPLE)
set(UNIX 1)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
endmacro()
endif()

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
NDK_TOOLCHAIN_VERSION := 4.8
APP_PLATFORM := android-9
APP_STL := c++_shared
APP_ABI := armeabi
APP_ABI := armeabi-v7a
APP_MODULES := sfml-activity sfml-example

View File

@ -1 +0,0 @@
target=android-19

View File

@ -56,7 +56,7 @@ include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
# build the list of external libraries to link
if(SFML_OS_ANDROID)
list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES)
list(APPEND AUDIO_EXT_LIBS android OpenSLES)
endif()
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})

View File

@ -138,7 +138,7 @@ endif()
if(SFML_OS_IOS)
list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES")
elseif(SFML_OS_ANDROID)
list(APPEND GRAPHICS_EXT_LIBS -lz)
list(APPEND GRAPHICS_EXT_LIBS z)
endif()
list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})

View File

@ -23,7 +23,6 @@
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <string>
#include <android/native_activity.h>
#include <android/log.h>
#include <dlfcn.h>
@ -37,13 +36,14 @@ namespace {
typedef void (*activityOnCreatePointer)(ANativeActivity*, void*, size_t);
}
std::string getLibraryName(JNIEnv* lJNIEnv, jobject& objectActivityInfo)
const char *getLibraryName(JNIEnv* lJNIEnv, jobject& objectActivityInfo)
{
// This function reads the value of meta-data "sfml.app.lib_name"
// found in the Android Manifest file and returns it. It performs the
// following Java code using the JNI interface:
//
// ai.metaData.getString("sfml.app.lib_name");
static char name[256];
// Get metaData instance from the ActivityInfo object
jclass classActivityInfo = lJNIEnv->FindClass("android/content/pm/ActivityInfo");
@ -58,7 +58,7 @@ std::string getLibraryName(JNIEnv* lJNIEnv, jobject& objectActivityInfo)
jmethodID methodGetString = lJNIEnv->GetMethodID(classBundle, "getString", "(Ljava/lang/String;)Ljava/lang/String;");
jstring valueString = (jstring)lJNIEnv->CallObjectMethod(objectMetaData, methodGetString, objectName);
// No meta-data "sfml.app.lib_name" was found so we abord and inform the user
// No meta-data "sfml.app.lib_name" was found so we abort and inform the user
if (valueString == NULL)
{
LOGE("No meta-data 'sfml.app.lib_name' found in AndroidManifest.xml file");
@ -68,10 +68,18 @@ std::string getLibraryName(JNIEnv* lJNIEnv, jobject& objectActivityInfo)
// Convert the application name to a C++ string and return it
const jsize applicationNameLength = lJNIEnv->GetStringUTFLength(valueString);
const char* applicationName = lJNIEnv->GetStringUTFChars(valueString, NULL);
std::string ret(applicationName, applicationNameLength);
if (applicationNameLength >= 256)
{
LOGE("The value of 'sfml.app.lib_name' must not be longer than 255 characters.");
exit(1);
}
strncpy(name, applicationName, applicationNameLength);
name[applicationNameLength] = '\0';
lJNIEnv->ReleaseStringUTFChars(valueString, applicationName);
return ret;
return name;
}
void* loadLibrary(const char* libraryName, JNIEnv* lJNIEnv, jobject& ObjectActivityInfo)
@ -159,7 +167,13 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
jobject ObjectActivityInfo = lJNIEnv->CallObjectMethod(ObjectPackageManager, MethodGetActivityInfo, ObjectComponentName, GET_META_DATA);
// Load our libraries in reverse order
loadLibrary("c++_shared", lJNIEnv, ObjectActivityInfo);
#if defined(STL_LIBRARY)
#define _SFML_QS(s) _SFML_S(s)
#define _SFML_S(s) #s
loadLibrary(_SFML_QS(STL_LIBRARY), lJNIEnv, ObjectActivityInfo);
#undef _SFML_S
#undef _SFML_QS
#endif
loadLibrary("sndfile", lJNIEnv, ObjectActivityInfo);
loadLibrary("openal", lJNIEnv, ObjectActivityInfo);
@ -177,8 +191,7 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
loadLibrary("sfml-network-d", lJNIEnv, ObjectActivityInfo);
#endif
std::string libName = getLibraryName(lJNIEnv, ObjectActivityInfo);
void* handle = loadLibrary(libName.c_str(), lJNIEnv, ObjectActivityInfo);
void* handle = loadLibrary(getLibraryName(lJNIEnv, ObjectActivityInfo), lJNIEnv, ObjectActivityInfo);
// Call the original ANativeActivity_onCreate function
activityOnCreatePointer ANativeActivity_onCreate = (activityOnCreatePointer)dlsym(handle, "ANativeActivity_onCreate");

View File

@ -227,7 +227,7 @@ elseif(SFML_OS_MACOSX)
elseif(SFML_OS_IOS)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion")
elseif(SFML_OS_ANDROID)
list(APPEND WINDOW_EXT_LIBS "-landroid")
list(APPEND WINDOW_EXT_LIBS android)
endif()
if(SFML_OPENGL_ES)
if(SFML_OS_LINUX)
@ -235,7 +235,7 @@ if(SFML_OPENGL_ES)
elseif(SFML_OS_IOS)
list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES")
elseif(SFML_OS_ANDROID)
list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM")
list(APPEND WINDOW_EXT_LIBS EGL GLESv1_CM)
endif()
else()
list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY})