7
votes

I am trying to build C++ NDK lib inside Android Studio.I have an external lib called json and the Clang compiler faild on localeconv.

json.hpp:11867: error: undefined reference to 'localeconv'

The locale.h header exists and located inside ndk dir sysroot/usr/include.

My toolchain looks like this:

Gradle: (Showing only the part relevant to NDK)

 externalNativeBuild {
        cmake {

            arguments "-DANDROID_PLATFORM_LEVEL=${platformVersion}",
                    '-DANDROID_TOOLCHAIN=clang', '-DANDROID_STL=gnustl_static'
        }

        ndk {
            abiFilters 'armeabi-v7a'

        }
    }

Cmake

 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11 -Wall")
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -frtti  -fexceptions  -Wall")

  //'native-lib' is the final .so that's packaged into apk
       target_link_libraries(native-lib
                   OPENAL
                   FREETYPE
                   android
                    EGL
                    ${OPENGL_LIB}
                    log
                    m
                    z
                    atomic
                    gnustl_static
                    ) 

And here is the linker command line:

[1/1] Linking CXX shared library ........\build\intermediates\cmake\debug\obj\armeabi-v7a\libnative-lib.so FAILED: cmd.exe /C "cd . && D:\Android\android-sdk\ndk-bundle\toolchains\llvm\prebuilt\windows-x86_64\bin\clang++.exe --target=armv7-none-linux-androideabi --gcc-toolchain=D:/Android/android-sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64 --sysroot=D:/Android/android-sdk/ndk-bundle/sysroot -fPIC -isystem D:/Android/android-sdk/ndk-bundle/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=19 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -frtti -fexceptions -Wall -O0 -fno-limit-debug-info -Wl,--exclude-libs,libgcc.a --sysroot D:/Android/android-sdk/ndk-bundle/platforms/android-19/arch-arm -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--fix-cortex-a8 -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so

The complete error:

"D:/Android/android-sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/libgnustl_static.a" && cd ." D:\XXXXX\XXXXXX\windows....\thirdparty\json/json.hpp:11867: error: undefined reference to 'localeconv' clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) ninja: build stopped: subcommand failed. :app:externalNativeBuildDebug FAILED

The target SDK is 21.Minimum SDK is 19.NDK Version: 15.0.4075724

The same code base is compiled fine in Visual Studio Android project which uses the same toolchain.

3

3 Answers

11
votes

The answer is - NDK version for SDK 19 doesn't implement the whole C++11 standard in the STL. locale.h header has stubs for localeconv() method, but the library doesn't implement it.The closest Android SDK that implement localeconv() is SDK 21.This is implicitly stated in the header <locale.h>

struct lconv* localeconv(void) __INTRODUCED_IN(21) __VERSIONER_NO_GUARD;

#if __ANDROID_API__ >= 21
locale_t duplocale(locale_t) __INTRODUCED_IN(21);
void freelocale(locale_t) __INTRODUCED_IN(21);
locale_t newlocale(int, const char*, locale_t) __INTRODUCED_IN(21);
#endif /* __ANDROID_API__ >= 21 */

char* setlocale(int, const char*);

#if __ANDROID_API__ >= 21
locale_t uselocale(locale_t) __INTRODUCED_IN(21);
#endif /* __ANDROID_API__ >= 21 */


#define LC_GLOBAL_LOCALE __BIONIC_CAST(reinterpret_cast, locale_t, -1L)

__END_DECLS

#endif /* _LOCALE_H_ */
0
votes

For me, trying to use Lua 5.4.0, I have to define the API level to 21

Cmake file as:

set(ANDROID_NATIVE_API_LEVEL    21)
0
votes

I had a similar problem, and unfortunaletly changing API level couldn't work for me --I was working with an old tablet which runs API16. You can try Crystax NDK or you can write an ugly function that mimics the localeconv(). The latter had solved my problem since I was building Lua for Android Terminal Emulator for hobby.