Commit 6ba71f4f authored by Thomas Guillem's avatar Thomas Guillem

build: restore c++_shared usage

This is a partial revert of the following commits
 - b775dbba "build: fix ODR violation"
 - b9df5331 "Use libc++ as static library"

UnsatisfiedLinkError with c++_shared should be fixed since we now use the last
NDK version and we dropped old android versions that triggered this crash.

This commit remove the ugly jniloader hack.

Here are the list of .so that are now shipped within the APK:
 - c++_shared.so (from the NDK)
 - libvlc.so (all VLC modules, VLC/LibVLC symbols) => link with c++_shared.so
 - libvlcjni.so (all JNI symbols) => link with libvlc.so
 - libmla.so (medialibrary, optional)  => link with libvlc.so and c++_shared.so

The APK size won't change with this commit (the difference of .so sizes is
negligible).
parent 2223df5f
......@@ -7,6 +7,9 @@ medialibrary/medialibrary
medialibrary/sqlite*
medialibrary/libvlcpp
medialibrary/build
medialibrary/jni/obj
medialibrary/jni/libs
medialibrary/.libs
# Android .so
/android-libs/**/*.so
......
......@@ -403,7 +403,7 @@ elif [ "${PLATFORM_SHORT_ARCH}" = "arm" ]; then
NDK_LIB_DIR="${NDK_LIB_DIR}/armv7-a"
fi
EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -L${NDK_LIB_DIR} -lc++abi -lc++_static"
EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -L${NDK_LIB_DIR} -lc++abi"
VLC_LDFLAGS="${EXTRA_LDFLAGS}"
# Release or not?
......@@ -669,6 +669,26 @@ rm ${REDEFINED_VLC_MODULES_DIR}/syms
VLC_MODULES=$(find_modules ${REDEFINED_VLC_MODULES_DIR})
VLC_CONTRIB_LDFLAGS=`for i in $(/bin/ls $VLC_CONTRIB/lib/pkgconfig/*.pc); do PKG_CONFIG_PATH="$VLC_CONTRIB/lib/pkgconfig/" pkg-config --libs $i; done |xargs`
echo -e "ndk-build vlc"
$ANDROID_NDK/ndk-build$OSCMD -C libvlc \
APP_STL="c++_shared" \
APP_CPPFLAGS="-frtti -fexceptions" \
VLC_SRC_DIR="$VLC_SRC_DIR" \
VLC_BUILD_DIR="$VLC_SRC_DIR/$VLC_BUILD_DIR" \
VLC_CONTRIB="$VLC_CONTRIB" \
VLC_CONTRIB_LDFLAGS="$VLC_CONTRIB_LDFLAGS" \
VLC_MODULES="$VLC_MODULES" \
VLC_LDFLAGS="$VLC_LDFLAGS -latomic" \
APP_BUILD_SCRIPT=jni/Android.mk \
APP_PLATFORM=android-${ANDROID_API} \
APP_ABI=${ANDROID_ABI} \
NDK_PROJECT_PATH=jni \
NDK_TOOLCHAIN_VERSION=clang \
NDK_DEBUG=${NDK_DEBUG} \
BUILD_ML=${BUILD_ML}
checkfail "ndk-build libvlc failed"
################
# MEDIALIBRARY #
......@@ -809,51 +829,29 @@ checkfail "medialibrary: make failed"
cd ${SRC_DIR}
MEDIALIBRARY_LDLIBS="-L${MEDIALIBRARY_BUILD_DIR}/build-android-$ANDROID_ABI/.libs -lmedialibrary \
MEDIALIBRARY_LDLIBS="-L$SRC_DIR/libvlc/jni/libs/$ANDROID_ABI -lvlc \
-L${MEDIALIBRARY_BUILD_DIR}/build-android-$ANDROID_ABI/.libs -lmedialibrary \
-L$SRC_DIR/vlc/contrib/contrib-android-$TARGET_TUPLE/jpeg/.libs -ljpeg \
-L$MEDIALIBRARY_MODULE_DIR/$SQLITE_RELEASE/build-$ANDROID_ABI/.libs -lsqlite3"
-L$MEDIALIBRARY_MODULE_DIR/$SQLITE_RELEASE/build-$ANDROID_ABI/.libs -lsqlite3 \
-L${NDK_LIB_DIR} -lc++abi ${NDK_LIB_UNWIND}"
if [ $ON_WINDOWS -eq 1 ]; then
OSCMD=.cmd
fi
###########
# LINKING #
###########
fi # ${BUILD_ML} = "1"
echo -e "ndk-build vlc"
$ANDROID_NDK/ndk-build$OSCMD -C libvlc \
APP_STL="c++_static" \
APP_CPPFLAGS="-frtti -fexceptions" \
VLC_SRC_DIR="$VLC_SRC_DIR" \
VLC_BUILD_DIR="$VLC_SRC_DIR/$VLC_BUILD_DIR" \
VLC_CONTRIB="$VLC_CONTRIB" \
VLC_CONTRIB_LDFLAGS="$VLC_CONTRIB_LDFLAGS" \
VLC_MODULES="$VLC_MODULES" \
VLC_LDFLAGS="$VLC_LDFLAGS -latomic" \
MEDIALIBRARY_LDLIBS="${MEDIALIBRARY_LDLIBS}" \
MEDIALIBRARY_INCLUDE_DIR=${MEDIALIBRARY_BUILD_DIR}/include \
$ANDROID_NDK/ndk-build$OSCMD -C medialibrary \
APP_STL="c++_shared" \
LOCAL_CPP_FEATURES="rtti exceptions" \
APP_BUILD_SCRIPT=jni/Android.mk \
APP_PLATFORM=android-${ANDROID_API} \
APP_ABI=${ANDROID_ABI} \
NDK_PROJECT_PATH=jni \
NDK_TOOLCHAIN_VERSION=clang \
NDK_DEBUG=${NDK_DEBUG} \
BUILD_ML=${BUILD_ML}
checkfail "ndk-build failed"
$ANDROID_NDK/ndk-build$OSCMD -C libvlc \
APP_BUILD_SCRIPT=jni/loader/Android.mk \
APP_PLATFORM=android-${ANDROID_API} \
APP_ABI=${ANDROID_ABI} \
NDK_PROJECT_PATH=jni/loader \
NDK_TOOLCHAIN_VERSION=clang
MEDIALIBRARY_LDLIBS="${MEDIALIBRARY_LDLIBS}" \
MEDIALIBRARY_INCLUDE_DIR=${MEDIALIBRARY_BUILD_DIR}/include \
NDK_DEBUG=${NDK_DEBUG}
checkfail "ndk-build failed for libvlc"
fi # ${BUILD_ML} = "1"
echo "Dumping dbg symbols info ${OUT_DBG_DIR}"
......@@ -862,3 +860,4 @@ OUT_DBG_DIR=.dbg/${ANDROID_ABI}
mkdir -p $OUT_DBG_DIR
cp -a libvlc/jni/obj/local/${ANDROID_ABI}/*.so ${OUT_DBG_DIR}
cp -a medialibrary/jni/obj/local/${ANDROID_ABI}/*.so ${OUT_DBG_DIR}
......@@ -37,6 +37,8 @@ mkdir -p "$TMP_PATH"/jni
cp -r "$SCRIPT_PATH"/libvlc/jni/libs "$TMP_PATH"
cp -r "$SCRIPT_PATH"/libvlc/jni/obj "$TMP_PATH"
cp -r "$SCRIPT_PATH"/medialibrary/jni/libs "$TMP_PATH"
cp -r "$SCRIPT_PATH"/medialibrary/jni/obj "$TMP_PATH"
ln -s "$TMP_PATH"/obj "$TMP_PATH"/jni
......
......@@ -6,7 +6,7 @@ android {
sourceSets {
main {
jni.srcDirs = [] // Prevent gradle from building native code with ndk; we have our own Makefile for it.
jniLibs.srcDirs = [ 'jni/libs', 'jni/loader/libs', 'private_libs/libs' ] // Where generated .so files are placed.
jniLibs.srcDirs = [ 'jni/libs' ] // Where generated .so files are placed.
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
......
LOCAL_PATH := $(call my-dir)
MEDIALIBRARY_JNI_DIR := $(LOCAL_PATH)/../../medialibrary/jni
# libvlc jni static library
# libvlcjni
include $(CLEAR_VARS)
LOCAL_MODULE := vlcjni_static
LOCAL_MODULE := libvlcjni
LOCAL_SRC_FILES := libvlcjni.c
LOCAL_SRC_FILES += libvlcjni-mediaplayer.c
LOCAL_SRC_FILES += libvlcjni-vlcobject.c
......@@ -11,17 +10,16 @@ LOCAL_SRC_FILES += libvlcjni-media.c libvlcjni-medialist.c libvlcjni-mediadiscov
LOCAL_SRC_FILES += libvlcjni-dialog.c
LOCAL_SRC_FILES += thumbnailer.c
LOCAL_SRC_FILES += std_logger.c
LOCAL_SRC_FILES += dummy.cpp
LOCAL_C_INCLUDES := $(VLC_SRC_DIR)/include $(VLC_BUILD_DIR)/include $(MEDIALIBRARY_JNI_DIR) $(LOCAL_PATH)/loader
LOCAL_C_INCLUDES := $(VLC_SRC_DIR)/include $(VLC_BUILD_DIR)/include $(MEDIALIBRARY_JNI_DIR)
LOCAL_CFLAGS := -std=c11
LOCAL_CXXFLAGS := -std=c++11
include $(BUILD_STATIC_LIBRARY)
LOCAL_LDLIBS := -llog
LOCAL_SHARED_LIBRARIES := libvlc
include $(BUILD_SHARED_LIBRARY)
# libvlc dynamic library
# libvlc
include $(CLEAR_VARS)
LOCAL_MODULE := vlcjni
LOCAL_SRC_FILES := libvlcjni-modules.c libvlcjni-symbols.c
LOCAL_MODULE := libvlc
LOCAL_SRC_FILES := libvlcjni-modules.c libvlcjni-symbols.c dummy.cpp
LOCAL_LDFLAGS := -L$(VLC_CONTRIB)/lib
LOCAL_LDLIBS := \
$(VLC_MODULES) \
......@@ -35,18 +33,7 @@ LOCAL_LDLIBS := \
-lavcodec -lebml \
-llua \
-lgcrypt -lgpg-error \
$(MEDIALIBRARY_LDLIBS) \
$(VLC_LDFLAGS) \
-llog
LOCAL_WHOLE_STATIC_LIBRARIES := libvlcjni_static
ifeq ($(BUILD_ML), 1)
LOCAL_WHOLE_STATIC_LIBRARIES += libmla
endif
LOCAL_CXXFLAGS := -std=c++11
include $(BUILD_SHARED_LIBRARY)
ifeq ($(BUILD_ML), 1)
JNILOADER_INCLUDES := $(LOCAL_PATH)/loader
$(call import-add-path, $(MEDIALIBRARY_JNI_DIR))
$(call import-module, .)
endif
/* Force ndk build system to link with c++_shared and install it */
......@@ -30,7 +30,7 @@
#include <vlc/vlc.h>
#include "jniloader.h"
#include <jni.h>
#include <android/api-level.h>
......@@ -40,6 +40,8 @@
struct fields fields;
#define VLC_JNI_VERSION JNI_VERSION_1_2
#define THREAD_NAME "libvlcjni"
JNIEnv *jni_get_env(const char *name);
......@@ -97,10 +99,15 @@ JNIEnv *jni_get_env(const char *name)
static std_logger *p_std_logger = NULL;
#endif
int VLCJNI_OnLoad(JavaVM *vm, JNIEnv* env)
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv* env = NULL;
// Keep a reference on the Java VM.
myVm = vm;
if ((*vm)->GetEnv(vm, (void**) &env, VLC_JNI_VERSION) != JNI_OK)
return -1;
/* Create a TSD area and setup a destroy callback when a thread that
* previously set the jni_env_key is canceled or exited */
if (pthread_key_create(&jni_env_key, jni_detach_thread) != 0)
......@@ -342,11 +349,17 @@ int VLCJNI_OnLoad(JavaVM *vm, JNIEnv* env)
#undef GET_CLASS
#undef GET_ID
return 0;
LOGD("JNI interface loaded.");
return VLC_JNI_VERSION;
}
void VLCJNI_OnUnload(JavaVM *vm, JNIEnv *env)
void JNI_OnUnload(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
if ((*vm)->GetEnv(vm, (void**) &env, VLC_JNI_VERSION) != JNI_OK)
return;
(*env)->DeleteGlobalRef(env, fields.IllegalStateException.clazz);
(*env)->DeleteGlobalRef(env, fields.IllegalArgumentException.clazz);
(*env)->DeleteGlobalRef(env, fields.RuntimeException.clazz);
......
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := jniloader
LOCAL_SRC_FILES := jniloader.c
LOCAL_LDFLAGS := -ldl -llog
include $(BUILD_SHARED_LIBRARY)
/*****************************************************************************
* jniloader.c
*****************************************************************************
* Copyright © 2017 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <dlfcn.h>
#include <stdbool.h>
#include <android/log.h>
#include "jniloader.h"
#define LOG_TAG "VLC"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
static void *handle;
static bool has_ml;
/* jniloader.so is a shared C library used to receive JNI_OnLoad callback.
* Indeed, as JNI_OnLoad is already implemented in VLC core for its internal
* configuration, we can't have an other JNI_OnLoad implementation inside the
* libvlcjni.so.
*/
int JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void**) &env, VLC_JNI_VERSION) != JNI_OK)
{
LOGE("GetEnv failed");
return -1;
}
handle = dlopen("libvlcjni.so", RTLD_LAZY);
if (!handle)
{
LOGE("could not link libvlcjni.so");
return -1;
}
int (*load)(JavaVM *, JNIEnv*);
load = dlsym(handle, "VLCJNI_OnLoad");
if (!load || load(vm, env) != 0)
{
if (!load)
LOGE("could not find VLCJNI_OnLoad");
else
LOGE("VLCJNI_OnLoad failed");
return -1;
}
/* MediaLibraryJNI_OnLoad is not mandatory */
load = dlsym(handle, "MediaLibraryJNI_OnLoad");
if (load && load(vm, env) != 0)
{
LOGE("MediaLibraryJNI_OnLoad failed");
return -1;
}
has_ml = !!load;
return VLC_JNI_VERSION;
}
void JNI_OnUnload(JavaVM *vm, void *reserved)
{
JNIEnv* env;
if ((*vm)->GetEnv(vm, (void**) &env, VLC_JNI_VERSION) != JNI_OK)
return;
void (*unload)(JavaVM *, JNIEnv*);
if (has_ml)
{
unload = dlsym(handle, "MediaLibraryJNI_OnUnload");
if (unload)
unload(vm, env);
else
LOGE("could not find MediaLibraryJNI_OnUnload");
}
unload = dlsym(handle, "VLCJNI_OnUnload");
if (unload)
unload(vm, env);
else
LOGE("could not find VLCJNI_OnUnload");
dlclose(handle);
}
/*****************************************************************************
* jniloader.h
*****************************************************************************
* Copyright © 2017 VLC authors and VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#include <jni.h>
#define VLC_JNI_VERSION JNI_VERSION_1_2
#ifdef __cplusplus
extern "C" {
#endif
int MediaLibraryJNI_OnLoad(JavaVM *vm, JNIEnv *env);
void MediaLibraryJNI_OnUnload(JavaVM *vm, JNIEnv *env);
int VLCJNI_OnLoad(JavaVM *vm, JNIEnv *env);
void VLCJNI_OnUnload(JavaVM *vm, JNIEnv *env);
#ifdef __cplusplus
}
#endif
......@@ -136,8 +136,9 @@ public class LibVLC extends VLCObject<LibVLC.Event> {
sLoaded = true;
try {
System.loadLibrary("c++_shared");
System.loadLibrary("vlc");
System.loadLibrary("vlcjni");
System.loadLibrary("jniloader");
} catch (UnsatisfiedLinkError ule) {
Log.e(TAG, "Can't load vlcjni library: " + ule);
/// FIXME Alert user
......
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := medialibrary.cpp AndroidMediaLibrary.cpp AndroidDeviceLister.cpp utils.cpp
LOCAL_MODULE := mla
LOCAL_C_INCLUDES := $(MEDIALIBRARY_INCLUDE_DIR) $(JNILOADER_INCLUDES)
LOCAL_CFLAGS := $(MEDIALIBRARY_CFLAGS)
include $(BUILD_STATIC_LIBRARY)
LOCAL_MODULE_FILENAME := libmla
LOCAL_LDLIBS := $(MEDIALIBRARY_LDLIBS) -llog
LOCAL_C_INCLUDES := $(MEDIALIBRARY_INCLUDE_DIR)
include $(BUILD_SHARED_LIBRARY)
#include "AndroidMediaLibrary.h"
#define LOG_TAG "VLC/JNI/AndroidMediaLibrary"
#include "log.h"
#include "jniloader.h"
#define THREAD_NAME "AndroidMedialibrary"
#define FLAG_MEDIA_UPDATED_AUDIO 1 << 0
......
......@@ -3,7 +3,7 @@
#include <algorithm>
#include <string>
#include "jniloader.h"
#include <jni.h>
#include <medialibrary/IDeviceLister.h>
#define LOG_TAG "VLC/JNI/MediaLibrary"
#include "log.h"
......@@ -1733,11 +1733,14 @@ static void jni_detach_thread(void *data)
myVm->DetachCurrentThread();
}
extern "C" {
int MediaLibraryJNI_OnLoad(JavaVM *vm, JNIEnv* env)
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv* env = NULL;
myVm = vm;
if (vm->GetEnv((void**) &env, VLC_JNI_VERSION) != JNI_OK)
return -1;
#define GET_CLASS(clazz, str, b_globlal) do { \
(clazz) = env->FindClass((str)); \
if (!(clazz)) { \
......@@ -1761,7 +1764,6 @@ int MediaLibraryJNI_OnLoad(JavaVM *vm, JNIEnv* env)
} \
} while (0)
jclass Version_clazz;
jfieldID SDK_INT_fieldID;
GET_CLASS(Version_clazz, "android/os/Build$VERSION", false);
......@@ -1960,17 +1962,22 @@ int MediaLibraryJNI_OnLoad(JavaVM *vm, JNIEnv* env)
#undef GET_CLASS
#undef GET_ID
return 0;
return VLC_JNI_VERSION;
}
void MediaLibraryJNI_OnUnload(JavaVM *vm, JNIEnv* env)
void JNI_OnUnload(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
if (vm->GetEnv((void**) &env, VLC_JNI_VERSION) != JNI_OK)
return;
env->DeleteGlobalRef(ml_fields.IllegalArgumentException.clazz);
env->DeleteGlobalRef(ml_fields.IllegalStateException.clazz);
env->DeleteGlobalRef(ml_fields.MediaLibrary.clazz);
env->DeleteGlobalRef(ml_fields.MediaWrapper.clazz);
}
}
static inline void throw_IllegalStateException(JNIEnv *env, const char *p_error)
{
......
......@@ -24,6 +24,8 @@
#include <medialibrary/Types.h>
#include <medialibrary/IMediaLibrary.h>
#define VLC_JNI_VERSION JNI_VERSION_1_2
struct fields {
jint SDK_INT;
struct IllegalStateException {
......
......@@ -9,6 +9,7 @@ import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread;
......@@ -100,6 +101,14 @@ public class Medialibrary {
|| dbDirectory == null || !dbDirectory.canWrite())
return ML_INIT_FAILED;
LibVLC.loadLibraries();
try {
System.loadLibrary("c++_shared");
System.loadLibrary("mla");
} catch (UnsatisfiedLinkError ule)
{
Log.e(TAG, "Can't load mla: " + ule);
return ML_INIT_FAILED;
}
int initCode = nativeInit(dbDirectory+ VLC_MEDIA_DB_NAME, extFilesDir+ THUMBS_FOLDER_NAME);
mIsInitiated = initCode != ML_INIT_FAILED;
return initCode;
......
......@@ -5,6 +5,11 @@ apply plugin: 'kotlin-kapt'
android {
packagingOptions {
exclude 'META-INF/main.kotlin_module'
pickFirst 'lib/armeabi-v7a/libc++_shared.so'
pickFirst 'lib/armeabi/libc++_shared.so'
pickFirst 'lib/arm64-v8a/libc++_shared.so'
pickFirst 'lib/x86/libc++_shared.so'
pickFirst 'lib/x86_64/libc++_shared.so'
}
dexOptions {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment