[UE4][Android NDK]error 'to_string' is not a member of 'std'
keywords: Android NDK, to_string, Build Failed, UE4, Unreal Engine 4
Steps in ordinary 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 was 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.
Origin:
#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.
5, Application would crash on startup, it is probably caused by missing libc++_shared.so
.
Solution:
Modify source:
\Engine\Source\Programs\UnrealBuildTool\Platform\Android\UEDeployAndroid.cs
Add following code inside function CopySTL
:
// copy libc++_shared.so
string SourceSTLSONameLLVM = Environment.ExpandEnvironmentVariables("%NDKROOT%/sources/cxx-stl/llvm-libc++/libs/") + NDKArch + "/libc++_shared.so";
string FinalSTLSONameLLVM = UE4BuildPath + "/libs/" + NDKArch + "/libc++_shared.so";
// remove from location for Ant if previously copied
string WrongSTLSOName = UE4BuildPath + "/libs/" + NDKArch + "/libgnustl_shared.so";
SafeDeleteFile(WrongSTLSOName);
// check to see if libgnustl_shared.so is newer than last time we copied
bool bFileExists = File.Exists(FinalSTLSONameLLVM);
TimeSpan Diff = File.GetLastWriteTimeUtc(FinalSTLSONameLLVM) - File.GetLastWriteTimeUtc(SourceSTLSONameLLVM);
if (!bFileExists || Diff.TotalSeconds < -1 || Diff.TotalSeconds > 1)
{
SafeDeleteFile(FinalSTLSOName);
Directory.CreateDirectory(Path.GetDirectoryName(FinalSTLSONameLLVM));
File.Copy(SourceSTLSONameLLVM, FinalSTLSONameLLVM, true);
}
6, If want to use a version of NDK higher than maximum version which defined in UE4, following source needs to be modified:
\Engine\Source\Programs\UnrealBuildTool\Platform\Android\AndroidToolChain.cs
Limitation of Minimum and Maxmum version of NDK:
// Android NDK toolchain that must be used for C++ compiling
readonly int MinimumNDKToolchain = 140100;
readonly int MaximumNDKToolchain = 180100;
readonly int RecommendedNDKToolchain = 140100;
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
与其更好,不如不同。