Native Singletons on Android platform ?

971 views
Skip to first unread message

hellho...@web.de

unread,
Apr 8, 2013, 3:49:37 AM4/8/13
to andro...@googlegroups.com
My native C++ project I've to port to android platform is based on several static and dynamic libraries, using c++11 based thread safe singletons,
which are shared between those modules.

Here is an example of my actual structure:

  brCore  (Core elements, Manager (Singletons), Logger (Singleton) ect.)  STATIC
  brGrapics (Generic graphics) uses brCore STATIC
  brOpenGLES (GLES renderer) uses brCore, brGraphics DYNAMIC
 
My Android Application (also DYNAMIC) uses those three libraries and loads brOpenGLES dynamically on startup.
On Linux and Windows platform anything is working fine, but on android, I got trouble with the Singletons:

04-08 06:47:24.601: I/NativeActivitySimpleExample(1059): brSingleton getInstance called
04-08 06:47:24.611: I/NativeActivitySimpleExample(1059): Singleton constructor invoked : brFileHandler 
04-08 06:47:24.611: I/NativeActivitySimpleExample(1059): brFileHandler set internal data path: /data/data/com.binrev/files
04-08 06:47:24.611: I/NativeActivitySimpleExample(1059): brSingleton getInstance called

04-08 06:47:24.031: I/NativeActivitySimpleExample(1059): Try to initialize Render API
04-08 06:47:24.031: I/NativeActivitySimpleExample(1059): brSingleton getInstance called
04-08 06:47:24.051: I/NativeActivitySimpleExample(1059): Singleton constructor invoked : brRessourceManager
04-08 06:47:24.051: I/NativeActivitySimpleExample(1059): brSingleton getInstance called

04-08 06:47:24.251: I/NativeActivitySimpleExample(1059): Try to init Logger: brCore
04-08 06:47:24.251: I/NativeActivitySimpleExample(1059): Search for existing logger
04-08 06:47:24.282: I/NativeActivitySimpleExample(1059): brSingleton getInstance called
04-08 06:47:24.282: I/NativeActivitySimpleExample(1059): Singleton constructor invoked : brRessourceManager

04-08 06:47:24.282: I/NativeActivitySimpleExample(1059): brSingleton getInstance called
04-08 06:47:24.282: I/NativeActivitySimpleExample(1059): Singleton constructor invoked : brConfigManager

04-08 06:47:24.601: I/NativeActivitySimpleExample(1059): brSingleton getInstance called
04-08 06:47:24.611: I/NativeActivitySimpleExample(1059): Singleton constructor invoked : brFileHandler
04-08 06:47:24.611: I/NativeActivitySimpleExample(1059): brSingleton getInstance called

As you can see, the constructor of the thread safe singletons is called multiple times, what not should be. Values set at the Singleton (brFileHandler internal data path)
are lost at later points. It looks like the libraries have separate instances of the singletons and could not share content among library boundaries...

How could I solve this problem?
Thanks for any help.

David Turner

unread,
Apr 8, 2013, 4:54:22 AM4/8/13
to andro...@googlegroups.com
Unfortunately, there is not enough information in your post to diagnose much of the problem, it would be nice if you could answer the following questions first:

1/ What is the exact implementation of your singleton?
2/ Which exact compiler / C++11 flags / C++ STL are you using ?
3/ How are linked your binaries (i.e. shared libraries + executables).

Keep in mind that:

- If you are using several binaries that all depend on a given C++ STL, you should use the dynamic version (e.g. gnustl_shared / stlport_shared). Using the static version will result in weird behaviour like the one you're describing (or even worse when using std::string or exceptions).

- static C++ constructors in static libraries are copied to _all_ the binaries that link against it. So if both brOpenGLES and Application link against brCore, they will each end up with a copy of the brCore singleton initializers.




--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk...@googlegroups.com.
To post to this group, send email to andro...@googlegroups.com.
Visit this group at http://groups.google.com/group/android-ndk?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

hellho...@web.de

unread,
Apr 8, 2013, 5:36:55 AM4/8/13
to andro...@googlegroups.com
I will try to answer your questions:

This is my generic Singleton template implementation, located in brCore module:

#define BINREV_SINGLETON_H__

#include <mutex>
#include <memory>
#include <thread>

#include <android/log.h>
#include <android_native_app_glue.h>

#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "NativeActivitySimpleExample", __VA_ARGS__))

namespace binrev{
namespace brCore{

template <typename T>
class brSingleton
{
public:
    static T& getInstance()
    {
        LOGI("brSingleton getInstance called");   
        std::call_once(m_once, safe_create);
        return *m_instance;       
    }

protected:
    brSingleton(const std::string& name)
    : m_name(name)
    {   
        LOGI("Singleton constructor invoked : %s", m_name.c_str());
    }
   
    static void safe_create() {
        brSingleton::m_instance.reset(new T());
    }
   
    brSingleton(const brSingleton& rs) = delete;
    brSingleton& operator = (const brSingleton& rs) = delete;
  
    virtual ~brSingleton(){}

protected:
    static std::unique_ptr<T>    m_instance;
    static std::once_flag m_once;        
    std::string m_name;
};

template<typename T>
std::once_flag brSingleton<T>::m_once;

}// ns-brCore
}// ns-binrev

And this is a example of the Singleton usage:

namespace binrev{
namespace brCore{

class CORE_LIBRARY_API brApplication : public brCore::brSingleton<brApplication>
{
friend class brCore::brSingleton<brApplication>;

public:
    enum eState
    {
        STATE_UNINITIALIZED=0,
        STATE_RUNNING,
        STATE_PAUSED
    };
   
    virtual ~brApplication(void);
    static brApplication& getInstance(); 
            
#ifdef ANDROID
    const std::string& getInternalFilePath(void) const;  
    const std::string& getInternalLibraryPath(void) const;
             
    ANativeWindow* getNativeWindow(void) const;
    void setNativeWindow(ANativeWindow* window);
       
    ANativeActivity* getNativeActivity(void) const;
   
    void init(struct android_app* state);
#endif   

protected:
    brApplication(void);
       
#ifdef ANDROID
    std::string m_filePath;
    std::string m_libPath;
   
    ANativeActivity* m_nativeActivity;
    ANativeWindow* m_nativeWindow;
#endif
};
} // ns brCore
} // ns binrev
#endif//BINREV_APPLICATION_H__

And cpp-module :

#define CORE_LIBRARY_EXPORT
#include <brCore/brApplication.h>

#include <brCore/brAssert.h>
#include <brCore/brLog.h>
#include <brCore/brStringUtils.h>
#include <brCore/exceptions/brIllegalArgumentException.h>
#include <brCore/exceptions/brIllegalStateException.h>
       
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "NativeActivitySimpleExample", __VA_ARGS__))
                                         
namespace binrev{
namespace brCore {

// Zero initialization of the static singleton instance
template <> std::unique_ptr<brApplication> brSingleton<brApplication>::m_instance = nullptr;
         
/** @brief Default Constructor */
brApplication::brApplication()
: brSingleton<brApplication>("brApplication")
{}

/** @brief Destructor */
brApplication::~brApplication()
{}

/*! @copydoc brCore::brSingleton::getInstance()
    @note
    Override standard Singleton creation. We have to do this to avoid
    linker errors on Windows platforms when trying to use the brSingleton
    base class from outside of a dll.    
*/
brApplication& brApplication::getInstance()
{
   // create instance calling parent method
   brCore::brSingleton<brApplication>::getInstance();
   return *m_instance;
}
 
And this is my Application.mk file, used by any module:

APP_MODULES := NativeActivitySimpleExample  
     
APP_CPPFLAGS := -std=gnu++0x 
APP_CPPFLAGS += -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -DDEBUG  
APP_CPPFLAGS += -rdynamic

APP_ABI := armeabi-v7a
APP_PLATFORM:=android-14                     

APP_STL := gnustl_static
APP_GNUSTL_CPP_FEATURES := rtti exceptions

NDK_TOOLCHAIN_VERSION=4.7

In the dynamic brGLES module I also use the following
flag:

APP_CPPFLAGS += -rdynamic

And this is the Android.mk file of my application:

LOCAL_PATH := $(call my-dir)

LOCAL_CFLAGS += -DDEBUG
LOCAL_CFLAGS += -DANDROID

include $(CLEAR_VARS)
LOCAL_MODULE := brCore
LOCAL_SRC_FILES := brCore/libbrCore.a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/brCore/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := brMath
LOCAL_SRC_FILES := brMath/libbrMath.a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/brMath/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := brGraphics
LOCAL_SRC_FILES := brGraphics/libbrGraphics.a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/brGraphics/include
LOCAL_LDLIBS += $(LOCAL_PATH)/brCore/libbrCore.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := NativeActivitySimpleExample
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2
LOCAL_LDLIBS += $(LOCAL_PATH)/jsoncpp/libjsoncpp.a  

LOCAL_STATIC_LIBRARIES += brGraphics
LOCAL_STATIC_LIBRARIES += brMath
LOCAL_STATIC_LIBRARIES += brCore

LOCAL_STATIC_LIBRARIES += android_native_app_glue

include $(BUILD_SHARED_LIBRARY)
$(call import-module, android/native_app_glue)

hellho...@web.de

unread,
Apr 8, 2013, 5:39:35 AM4/8/13
to andro...@googlegroups.com
Edit: In brGLES module I use:

APP_CPPFLAGS += -fpic

instead of -rdynamic.

David Turner

unread,
Apr 8, 2013, 8:47:18 AM4/8/13
to andro...@googlegroups.com
Thanks for the details, this helps a bit, but since you're using prebuilt static libraries, I can't really see what's in there. For example, how many times is the source code for the brFileHandler singleton being compiled? If it is in both brCore and brGraphics, then this would easily explain the behaviour you're seeing.

Can you show the final link command for libNativeActivitySimpleExample.so though? Use "ndk-build V=1" to show it.

If you are only generating a single shared library, as shown in the example above, using gnustl_static is ok. However, your original post talked about another shared library (brOpenGLES) which doesn't appear in the example. If would be nice if you could clarify if the issue happens when you don't use this library, or not.

It would be nice if you could find a way to reproduce the issue. Also, on which Android platform are you running this? I believe a bug was fixed after Eclair, where the dynamic linker would run static C++ constructors twice at load time (but this would be reflected for all singleton classes then, so it's probably not what you're seeing).

Apart from that, a few notes:

1/ Don't test against ANDROID, use __ANDROID__ instead. This one is defined by the compiler so you don't need to add "LOCAL_CFLAGS += -DANDROID" to your Android.mk

2/ The LOCAL_LDLIBS in your brGraphics declaration is un-necessary. All LOCAL_LDLIBS / LOCAL_LDFLAGS values are ignored in static libraries. If you want to say that brGraphics depends on brCore, all you need is "LOCAL_STATIC_LIBRARIES += brCore" instead.

3/ I'd recommend adding a prebuilt static library declaration for a 'jsoncpp' module as well, and use "LOCAL_STATIC_LIBRARIES += jsoncpp" in your final Android.mk. LOCAL_LDLIBS should really only be used for adding system library dependencies (like -lEGL).

hellho...@web.de

unread,
Apr 8, 2013, 9:38:13 AM4/8/13
to andro...@googlegroups.com
Thanks for the informations. I try to show, how I actually build my project. Actually I use in each module
a prebuild of any dependency:

            brCore       --> Prebuild  jsoncpp
            brGraphics --> Prebuild brCore
            brGLES     --> Prebuild brCore, brGraphics

            Application --> Prebuild brCore, brGraphics dynamically load brGLES

Is there a way to integrate those dependencies without an explicitly prebuild in each module?
Here is the verbose information of my acutal build:

d:\development\android\workspace\NdkTest-native>d:\development\android\ndk-r8e\n
dk-build V=1 -B
d:/development/android/ndk-r8e/build/core/add-application.mk:128: Android NDK: W
ARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 10 in ./And
roidManifest.xml
del /f/q .\libs\armeabi-v7a\libbrOpenGLES2.so .\libs\armeabi-v7a\libgnustl_share
d.so .\libs\armeabi-v7a\libNativeActivitySimpleExample.so   >NUL 2>NUL
"Compile++ thumb : NativeActivitySimpleExample <= main.cpp
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi-v7a/objs/Nat
iveActivitySimpleExample/main.o.d -fpic -ffunction-sections -funwind-tables -fst
ack-protector -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfp
v3-d16 -fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -f
no-strict-aliasing -finline-limit=64 -Ijni/brGraphics/include -Ijni/brMath/inclu
de -Ijni/brCore/include -Id:/development/android/ndk-r8e/sources/android/native_
app_glue -Id:/development/android/ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.7/incl
ude -Id:/development/android/ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.7/libs/arme
abi-v7a/include -Ijni -DANDROID  -Wa,--noexecstack    -std=gnu++0x -frtti -fexce
ptions -DDEBUG -rdynamic  -Id:/development/android/ndk-r8e/platforms/android-14/
arch-arm/usr/include -c  jni/main.cpp -o ./obj/local/armeabi-v7a/objs/NativeActi
vitySimpleExample/main.o
Prebuilt       : libgnustl_shared.so <= <NDK>/sources/cxx-stl/gnu-libstdc++/4.7/
libs/armeabi-v7a/
copy /b/y "d:\development\android\ndk-r8e\sources\cxx-stl\gnu-libstdc++\4.7\libs
\armeabi-v7a\libgnustl_shared.so" "obj\local\armeabi-v7a\libgnustl_shared.so" >
NUL
"Compile thumb : android_native_app_glue <= android_native_app_glue.c
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-gcc -MMD -MP -MF ./obj/local/armeabi-v7a/objs/and
roid_native_app_glue/android_native_app_glue.o.d -fpic -ffunction-sections -funw
ind-tables -fstack-protector -no-canonical-prefixes -march=armv7-a -mfloat-abi=s
oftfp -mfpu=vfpv3-d16 -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-a
liasing -finline-limit=64 -Id:/development/android/ndk-r8e/sources/android/nativ
e_app_glue -DANDROID  -Wa,--noexecstack  -Id:/development/android/ndk-r8e/platfo
rms/android-14/arch-arm/usr/include -c  d:/development/android/ndk-r8e/sources/a
ndroid/native_app_glue/android_native_app_glue.c -o ./obj/local/armeabi-v7a/objs
/android_native_app_glue/android_native_app_glue.o
StaticLibrary  : libandroid_native_app_glue.a
del /f/q obj\local\armeabi-v7a\libandroid_native_app_glue.a >NUL 2>NUL
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-ar crs ./obj/local/armeabi-v7a/libandroid_native_
app_glue.a ./obj/local/armeabi-v7a/objs/android_native_app_glue/android_native_a
pp_glue.o
SharedLibrary  : libNativeActivitySimpleExample.so
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-g++ -Wl,-soname,libNativeActivitySimpleExample.so
 -shared --sysroot=d:/development/android/ndk-r8e/platforms/android-14/arch-arm
./obj/local/armeabi-v7a/objs/NativeActivitySimpleExample/main.o jni/brGraphics/l
ibbrGraphics.a jni/brMath/libbrMath.a jni/brCore/libbrCore.a ./obj/local/armeabi
-v7a/libandroid_native_app_glue.a -lgcc ./obj/local/armeabi-v7a/libgnustl_shared
.so -no-canonical-prefixes -march=armv7-a -Wl,--fix-cortex-a8  -Wl,--no-undefine
d -Wl,-z,noexecstack -Wl,-z,relro -Wl,-z,now  -Ld:/development/android/ndk-r8e/p
latforms/android-14/arch-arm/usr/lib -llog -landroid -lEGL -lGLESv2 jni/jsoncpp/
libjsoncpp.a -lgnustl_shared -llog d:/development/android/ndk-r8e/sources/cxx-st
l/gnu-libstdc++/4.7/libs/armeabi-v7a/libsupc++.a -lc -lm -o ./obj/local/armeabi-
v7a/libNativeActivitySimpleExample.so
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/../lib/gcc/arm-linux-androideabi/4.7/../../../../arm-linux-androideabi/
bin/ld.exe: error: cannot find -lgnustl_shared
collect2.exe: error: ld returned 1 exit status
make: *** [obj/local/armeabi-v7a/libNativeActivitySimpleExample.so] Error 1

d:\development\android\workspace\NdkTest-native>d:\development\android\ndk-r8e\n
dk-build V=1 -B
d:/development/android/ndk-r8e/build/core/add-application.mk:128: Android NDK: W
ARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 10 in ./And
roidManifest.xml
"Compile++ thumb : NativeActivitySimpleExample <= main.cpp
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-g++ -MMD -MP -MF ./obj/local/armeabi-v7a/objs/Nat
iveActivitySimpleExample/main.o.d -fpic -ffunction-sections -funwind-tables -fst
ack-protector -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfp
v3-d16 -fno-exceptions -fno-rtti -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -f
no-strict-aliasing -finline-limit=64 -Ijni/brGraphics/include -Ijni/brMath/inclu
de -Ijni/brCore/include -Id:/development/android/ndk-r8e/sources/android/native_
app_glue -Id:/development/android/ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.7/incl
ude -Id:/development/android/ndk-r8e/sources/cxx-stl/gnu-libstdc++/4.7/libs/arme
abi-v7a/include -Ijni -DANDROID  -Wa,--noexecstack    -std=gnu++0x -frtti -fexce
ptions -DDEBUG -rdynamic  -Id:/development/android/ndk-r8e/platforms/android-14/
arch-arm/usr/include -c  jni/main.cpp -o ./obj/local/armeabi-v7a/objs/NativeActi
vitySimpleExample/main.o
"Compile thumb : android_native_app_glue <= android_native_app_glue.c
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-gcc -MMD -MP -MF ./obj/local/armeabi-v7a/objs/and
roid_native_app_glue/android_native_app_glue.o.d -fpic -ffunction-sections -funw
ind-tables -fstack-protector -no-canonical-prefixes -march=armv7-a -mfloat-abi=s
oftfp -mfpu=vfpv3-d16 -mthumb -Os -g -DNDEBUG -fomit-frame-pointer -fno-strict-a
liasing -finline-limit=64 -Id:/development/android/ndk-r8e/sources/android/nativ
e_app_glue -DANDROID  -Wa,--noexecstack  -Id:/development/android/ndk-r8e/platfo
rms/android-14/arch-arm/usr/include -c  d:/development/android/ndk-r8e/sources/a
ndroid/native_app_glue/android_native_app_glue.c -o ./obj/local/armeabi-v7a/objs
/android_native_app_glue/android_native_app_glue.o
StaticLibrary  : libandroid_native_app_glue.a
del /f/q obj\local\armeabi-v7a\libandroid_native_app_glue.a >NUL 2>NUL
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-ar crs ./obj/local/armeabi-v7a/libandroid_native_
app_glue.a ./obj/local/armeabi-v7a/objs/android_native_app_glue/android_native_a
pp_glue.o
SharedLibrary  : libNativeActivitySimpleExample.so
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-g++ -Wl,-soname,libNativeActivitySimpleExample.so
 -shared --sysroot=d:/development/android/ndk-r8e/platforms/android-14/arch-arm
./obj/local/armeabi-v7a/objs/NativeActivitySimpleExample/main.o jni/brGraphics/l
ibbrGraphics.a jni/brMath/libbrMath.a jni/brCore/libbrCore.a ./obj/local/armeabi
-v7a/libandroid_native_app_glue.a d:/development/android/ndk-r8e/sources/cxx-stl
/gnu-libstdc++/4.7/libs/armeabi-v7a/libgnustl_static.a -lgcc -no-canonical-prefi
xes -march=armv7-a -Wl,--fix-cortex-a8  -Wl,--no-undefined -Wl,-z,noexecstack -W
l,-z,relro -Wl,-z,now  -Ld:/development/android/ndk-r8e/platforms/android-14/arc
h-arm/usr/lib -llog -landroid -lEGL -lGLESv2 jni/jsoncpp/libjsoncpp.a -llog -lc
-lm -o ./obj/local/armeabi-v7a/libNativeActivitySimpleExample.so
Install        : libNativeActivitySimpleExample.so => libs/armeabi-v7a/libNative
ActivitySimpleExample.so
copy /b/y ".\obj\local\armeabi-v7a\libNativeActivitySimpleExample.so" ".\libs\ar
meabi-v7a\libNativeActivitySimpleExample.so" > NUL
d:/development/android/ndk-r8e/toolchains/arm-linux-androideabi-4.7/prebuilt/win
dows/bin/arm-linux-androideabi-strip --strip-unneeded  ./libs/armeabi-v7a/libNat
iveActivitySimpleExample.so

brOpenGLES also uses STL static. Here are my actuall settings for GLES, which must
be build dynamically, while I've to import it as plug-in on runtime:

LOCAL_PATH := $(call my-dir)

LOCAL_CFLAGS += -DDEBUG
LOCAL_CFLAGS += -DANDROID

include $(CLEAR_VARS)
LOCAL_MODULE := brCore
LOCAL_SRC_FILES := brCore/libbrCore.a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/brCore/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := brMath
LOCAL_SRC_FILES := brMath/libbrMath.a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/brMath/include
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := brGraphics
LOCAL_SRC_FILES := brGraphics/libbrGraphics.a
LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)/brGraphics/include
LOCAL_LDLIBS += $(LOCAL_PATH)/brCore/libbrCore.a
include $(PREBUILT_STATIC_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := brOpenGLES2
LOCAL_SRC_FILES :=  EGL/brEGLContext.cpp \
                    EGL/brEGLSupport.cpp \
                    EGL/brEGLWindow.cpp  \
                    EGL/Android\brEGLAndroidSupport.cpp \
                    EGL/Android\brEGLAndroidWindow.cpp  \
                    GLSL/brGLSLLinker.cpp \
                    GLSL/brGLSLProgram.cpp \
                    GLSL/brGLSLShader.cpp \
                    GLSL/brGLSLShaderFactory.cpp \
                    GLSL/brGLSLSupport.cpp \
                    brGLES2Context.cpp \
                    brGLES2DataBufferFactory.cpp \
                    brGLES2Mapping.cpp \
                    brGLES2Plugin.cpp \
                    brGLES2Renderer.cpp \
                    brGLES2Support.cpp \
                    brGLES2VertexBuffer.cpp \
                    extension/brGLVertexBufferObject.cpp



LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2
LOCAL_LDLIBS += $(LOCAL_PATH)/jsoncpp/libjsoncpp.a  

LOCAL_STATIC_LIBRARIES += brGraphics
LOCAL_STATIC_LIBRARIES += brMath
LOCAL_STATIC_LIBRARIES += brCore

LOCAL_STATIC_LIBRARIES += android_native_app_glue

include $(BUILD_SHARED_LIBRARY)
$(call import-module, android/native_app_glue)

Actually I try to build my sources for honeycomb+. Thanks for your notes, I will
implement those asap.

hellho...@web.de

unread,
Apr 8, 2013, 9:43:48 AM4/8/13
to andro...@googlegroups.com
You have recommended that I also should use a Prebuild for jsoncpp, which I use
in brCore module. This was a try to avoid multiple predefinitions of jsoncpp in each
module.

May be this a solution to avoid a compile of my modules multiple times? Should I
use in any module LOCAL_LDLIBS += $(LOCAL_PATH)/brCore/libbrCore.a instead ?

David Turner

unread,
Apr 8, 2013, 10:10:17 AM4/8/13
to andro...@googlegroups.com
On Mon, Apr 8, 2013 at 3:38 PM, Hellho...@web.de <hellho...@web.de> wrote:
Thanks for the informations. I try to show, how I actually build my project. Actually I use in each module
a prebuild of any dependency:

            brCore       --> Prebuild  jsoncpp
            brGraphics --> Prebuild brCore
            brGLES     --> Prebuild brCore, brGraphics

            Application --> Prebuild brCore, brGraphics dynamically load brGLES


So it looks like you're generating both a shared library and an executable. You should really use gnustl_shared to avoid problems then.

Another issue is that you're statically linking jsoncpp, brCore and brGraphics into both brGLES and Application, it means that both ELF binaries
will get an independent copy of every global variable present in these static libraries (including a _different_ singleton instance in each one of them).
 
Is there a way to integrate those dependencies without an explicitly prebuild in each module?

I'm not sure what you mean, but normally, you should be able to build these static libraries directly if there is a valid Android.mk for them.
What's the reason for using prebuilt binaries exactly?
Where does this extra -lgnustl_shared comes from? You should not need this in your LOCAL_LDLIBS as long
as you used APP_STL := gnustl_shared. It's the reason for your linking error.

hellho...@web.de

unread,
Apr 8, 2013, 3:24:58 PM4/8/13
to andro...@googlegroups.com

    So it looks like you're generating both a shared library and an executable. You should really use gnustl_shared to avoid problems then.

  
 Yes, GLES is the shared library and the Application is the executable. I will change to gnustl_shared.


    Another issue is that you're statically linking jsoncpp, brCore and brGraphics into both brGLES and Application, it means that both ELF binaries
    will get an independent copy of every global variable present in these static libraries (including a _different_ singleton instance in each one of them).


Ok, may it be a solution to build any library with Singleton as shared library? On Linux and Windows I already use shared libs for those
modules. I've switched on android to static modules, while I've to load those libraries explicitly before I could use them, which is not required
on Linux and Windows platform.


    I'm not sure what you mean, but normally, you should be able to build these static libraries directly if there is a valid Android.mk for them.
    What's the reason for using prebuilt binaries exactly?


My engine is split in modules, and plug-ins which are build separately. On Linux and Windows I install those libraries before usage. Any
dependency between those modules is solved by the installation path. While this is not possible on Android I use prebuilds. This is the only
mechanism I know to integrate modular sources.


Where does this extra -lgnustl_shared comes from? You should not need this in your LOCAL_LDLIBS as long
as you used APP_STL := gnustl_shared. It's the reason for your linking error.

This comes from my try and error tests. I've removed this.

David Turner

unread,
Apr 10, 2013, 9:11:34 AM4/10/13
to andro...@googlegroups.com
On Mon, Apr 8, 2013 at 9:24 PM, Hellho...@web.de <hellho...@web.de> wrote:

    So it looks like you're generating both a shared library and an executable. You should really use gnustl_shared to avoid problems then.

  
 Yes, GLES is the shared library and the Application is the executable. I will change to gnustl_shared.


    Another issue is that you're statically linking jsoncpp, brCore and brGraphics into both brGLES and Application, it means that both ELF binaries
    will get an independent copy of every global variable present in these static libraries (including a _different_ singleton instance in each one of them).


Ok, may it be a solution to build any library with Singleton as shared library? On Linux and Windows I already use shared libs for those
modules. I've switched on android to static modules, while I've to load those libraries explicitly before I could use them, which is not required
on Linux and Windows platform.


Yes, each singleton (or global variable) you need should be in a single shared library, or they will get duplicated, which is not what you want most of the time (nothing Android-specific here).
You will have to load libraries in reverse dependency order explicitely though for Android.
 

    I'm not sure what you mean, but normally, you should be able to build these static libraries directly if there is a valid Android.mk for them.
    What's the reason for using prebuilt binaries exactly?


My engine is split in modules, and plug-ins which are build separately. On Linux and Windows I install those libraries before usage. Any
dependency between those modules is solved by the installation path. While this is not possible on Android I use prebuilds. This is the only
mechanism I know to integrate modular sources.


I see, using PREBUILT_STATIC_LIBRARY or PREBUILT_SHARED_LIBRARY is the preferred way to go when actually doing this.
In theory, you could add the libraries directly to your LOCAL_LDLIBS but this is very fragile and requires that you know exactly what you're doing, especially in terms of dependencies (order is important at link time, unfortunately).

Also prebuilt NDK modules allow you to use LOCAL_EXPORT_XXXX, which generally makes using the prebuilts much easier too.

hellho...@web.de

unread,
Apr 11, 2013, 12:53:38 AM4/11/13
to andro...@googlegroups.com
Meanwhile I solved this issue following your recommendations by using shared libraries for my modules.
Thanks for your great explanations and patience.
Reply all
Reply to author
Forward
0 new messages