keywords: UE4, Android NDK, OpenSSL, SSL, curl, libcurl.a, libssl.a, libcrypto.a

Issue 1: multiple definition of functions of ssl

Error log when building Android package:

D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: G:/EpicGames/UnrealEngine4.22/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(s23_clnt.o): multiple definition of 'ssl_fill_hello_random'
UATHelper: Packaging (Android (ASTC)):     D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: 
UATHelper: Packaging (Android (ASTC)):     D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: G:/EpicGames/UnrealEngine4.22/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(s3_both.o): multiple definition of 'ssl3_do_write'
UATHelper: Packaging (Android (ASTC)):     D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: 
UATHelper: Packaging (Android (ASTC)):     D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: G:/EpicGames/UnrealEngine4.22/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(s3_both.o): multiple definition of 'ssl3_output_cert_chain'
UATHelper: Packaging (Android (ASTC)):     D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld:
UATHelper: Packaging (Android (ASTC)):     D:/sdks/Android/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/../../../../arm-linux-androideabi/bin\ld: error: G:/EpicGames/UnrealEngine4.22/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(s3_both.o): multiple definition of 'ssl_cert_type'

PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_unload_strings'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_put_error'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_get_state'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_clear_error'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_get_error'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_get_error_line'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_get_error_line_data'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_peek_error'
PackagingResults: Error: G:/EpicGames/UnrealEngine422_spatialos/Engine/Source/ThirdParty/libcurl/lib/Android/ARMv7/libcurl.a(err.o): multiple definition of 'ERR_peek_error_line'

Cause:

libcurl.a included in engine has included openssl library.

libcurl.a path:

\Engine\Source\ThirdParty\libcurl\lib\Android\ARM64\libcurl.a

Solution:
Replace libcurl.a with a pure curl library.
Download curl sources:
https://github.com/dawnarc/libcurl_in_pure_llvm

Issue 2: undefined reference to ‘X509_STORE_CTX_get_chain’

Error log when building Android package:

G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslCertificateManager.cpp:183: error: undefined reference to 'X509_STORE_CTX_get_chain'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslCertificateManager.cpp:184: error: undefined reference to 'sk_num'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslCertificateManager.cpp:211: error: undefined reference to 'sk_value'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:44: error: undefined reference to 'SSL_load_error_strings'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:46: error: undefined reference to 'SSL_library_init'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:47: error: undefined reference to 'OPENSSL_add_all_algorithms_noconf'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:66: error: undefined reference to 'EVP_cleanup'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:67: error: undefined reference to 'CRYPTO_cleanup_all_ex_data'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:68: error: undefined reference to 'ERR_free_strings'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:70: error: undefined reference to 'CONF_modules_free'
G:\EpicGames\UnrealEngine4.22\Engine\Source\Runtime\Online\SSL\Private/SslManager.cpp:82: error: undefined reference to 'SSLv23_client_method'
clang++: error: linker command failed with exit code 1 (use -v to see invocation)

Cause:
OpenSSL version used in engine is too old, so new functions of ssl don’t support in UE4.

Old ssl library path:

\Engine\Source\ThirdParty\OpenSSL\1_0_2h\lib\Android\ARM64\libssl.a

Solution:
Modify building configuration.
Building configuration path:

\Engine\Source\ThirdParty\OpenSSL\OpenSSL.Build.cs

Origin:

else if (Target.Platform == UnrealTargetPlatform.Android)
{
    string IncludePath = OpenSSL101sPath + "/include/Android";
    PublicIncludePaths.Add(IncludePath);

    // unneeded since included in libcurl
    // string LibPath = Path.Combine(OpenSSL101sPath, "lib", PlatformSubdir);
    //PublicLibraryPaths.Add(LibPath);
}

New:

else if (Target.Platform == UnrealTargetPlatform.Android)
{
    string IncludePath = OpenSSL111Path + "/include/Android/ARMv7";
    string LibraryPath = OpenSSL111Path + "/lib/Android";

    PublicIncludePaths.Add(IncludePath);

    PublicAdditionalLibraries.Add(LibraryPath + "/libssl.a");
    PublicAdditionalLibraries.Add(LibraryPath + "/libcrypto.a");
}

then replace libssl.a with new version building library.
destination directory:

\Engine\Source\ThirdParty\OpenSSL\1.1.1\Lib\Android

Download NDK library of 1.1.1 ssh:
https://github.com/leenjewel/openssl_for_ios_and_android/releases/tag/android_openssl-1.1.1a

Issue 3: expected unqualified-id uint32_t xor;

Error log when building Android package:

include\internal/constant_time_locl.h:274:18: error: expected unqualified-id uint32_t xor = *a ^ *b;

Cause:
xor is a keyword of Clang.

Solution:
Rename variables;

Issue 4: use of undeclared identifier ‘strtof_l’

Error log when building Android package:

D:/sdks/Android/android-ndk-r16b/sources/cxx-stl/llvm-libc++/include\locale(807,12):  error: use of undeclared identifier 'strtof_l'
return strtof_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
^
D:/sdks/Android/android-ndk-r16b/sources/cxx-stl/llvm-libc++/include\locale(813,12):  error: use of undeclared identifier 'strtod_l'; did you mean 'strtold_l'?
return strtod_l(__a, __p2, _LIBCPP_GET_C_LOCALE);
^
D:/sdks\Android\android-ndk-r16b\sysroot\usr\include\stdlib.h(237,13):  note: 'strtold_l' declared here
long double strtold_l(const char* __s, char** __end_ptr, locale_t __l) __INTRODUCED_IN(21);
^
2 errors generated.
Error: use of undeclared identifier 'strtof_l'
Error: use of undeclared identifier 'strtod_l'; did you mean 'strtold_l'?

Cause:
NDK version is too old.

Solution:
Switch NDK version to newer versoin.


扛得住事儿,就是才华横溢。