keywords: Android NDK, to_string, Build Failed, UE4, Unreal Engine 4

Steps in Common Anroid NDK Projects

Case:
Build with Android NDK failed:

error: 'to_string' is not a member of 'std'

Solution:

Add C++11 support in Application.mk if building static libraries:

APP_STL := c++_static

or use c++_shared if building shared libraries:

APP_STL := c++_shared

It doesn’t take effect if add APP_STL := gnustl_static in Application.mk, because gnustl is the C++ standard library of GCC and it doesn’t support C++11 fully.
c++_static and c++_shared means using libc++ which is the C++ standard library of LLVM, not GCC.

LLVM’s libc++ was stable in NDK r18, and GCC had been removed from r18, Clang is the default compiler.

Steps in UE4 Android Packaging

1, Modify function SetUpSpecificEnvironment which in UEBuildAndroid.cs.
path:

\Engine\Source\Programs\UnrealBuildTool\Platform\Android\UEBuildAndroid.cs
  • Modification 1st:
    Origin:

    string GccVersion = "4.6";
    int NDKVersionInt = ToolChain.GetNdkApiLevelInt();
    if (Directory.Exists(Path.Combine(NDKPath, @"sources/cxx-stl/gnu-libstdc++/4.9")))
    {
        GccVersion = "4.9";
    } else
    if (Directory.Exists(Path.Combine(NDKPath, @"sources/cxx-stl/gnu-libstdc++/4.8")))
    {
        GccVersion = "4.8";
    }
    

    New:

    string GccVersion = "4.6";
    int NDKVersionInt = ToolChain.GetNdkApiLevelInt();
    if (Directory.Exists(Path.Combine(NDKPath, @"sources/cxx-stl/llvm-libc++/4.9")))
    {
        GccVersion = "4.9";
    } else
    if (Directory.Exists(Path.Combine(NDKPath, @"sources/cxx-stl/llvm-libc++/4.8")))
    {
        GccVersion = "4.8";
    }
    
  • Modification 2nd:
    Origin:

    DirectoryReference NdkDir = new DirectoryReference(NDKPath);
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/include"));
    
    // the toolchain will actually filter these out
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/armeabi-v7a/include"));
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/arm64-v8a/include"));
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/x86/include"));
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/x86_64/include"));
    
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/armeabi-v7a"));
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/arm64-v8a"));
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/x86"));
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/gnu-libstdc++/" + GccVersion + "/libs/x86_64"));
    

    New:

    DirectoryReference NdkDir = new DirectoryReference(NDKPath);
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/llvm-libc++/include"));
    
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/llvm-libc++/libs/armeabi-v7a"));
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/llvm-libc++/libs/arm64-v8a"));
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/llvm-libc++/libs/x86"));
    LinkEnvironment.LibraryPaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/llvm-libc++/libs/x86_64"));
    
    CompileEnvironment.SystemIncludePaths.Add(DirectoryReference.Combine(NdkDir, "sources/cxx-stl/llvm-libc++abi/include"));
    
  • Modification 3rd:
    Origin:

    LinkEnvironment.AdditionalLibraries.Add("gnustl_shared");
    

    New:

    LinkEnvironment.AdditionalLibraries.Add("c++_shared");
    

\Engine\Build\Android\Java\jni\Application.mk doesn’t take effect any more.

2, Change system environment variables of NDK, e.g. the newest NDK version UE4 support is 14b(from v4.21).

NDK Environment variables using in UEBuildAndroid.cs called NDKROOT.

3, Modify PhysX3

Source Path:

\Engine\Source\ThirdParty\PhysX3\PxShared\include\foundation\unix\PxUnixIntrinsics.h

Add #include <cmath> in the top of source.
Orgin:

#if PX_ANDROID
    // If cmath is included after math.h, it will undefine isfinite. If that's the case, use the version in the std namespace instead.
    #ifndef isfinite
        using std::isfinite;
    #endif
#endif

New:

#if PX_ANDROID
    // If cmath is included after math.h, it will undefine isfinite. If that's the case, use the version in the std namespace instead.
    #ifndef isfinite
        #include <cmath>
        using std::isfinite;
    #endif
#endif

4, Remove plugin OnlineSubsystemGooglePlay and third party GooglePlay.
Directory:

\Engine\Plugins\Online\Android\OnlineSubsystemGooglePlay\

\Engine\Source\ThirdParty\GooglePlay\

Or replace them with newest version of these third parties sources if using them.

Reference

Android ndk std::to_string support
https://stackoverflow.com/questions/22774009/android-ndk-stdto-string-support%3E

error: ‘to_string’ is not a member of ‘std’
https://stackoverflow.com/questions/26095886/error-to-string-is-not-a-member-of-std

C++ Library Support
https://developer.android.com/ndk/guides/cpp-support


与其更好,不如不同。