Search code examples
c++creact-nativeandroid-ndk

React Native Android C++ TurboModules static C library linking problems


I was trying to link a C static lib with an RN Android C++ TurboModules project via CMakeLists and got blocked by errors. From my understanding, libc should be provided OOTB, but it's not linking somehow. I forced building only for arm64-v8a atm, and the C lib is also compiled for this architecture.

CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)

set (CMAKE_VERBOSE_MAKEFILE ON)
set (CMAKE_CXX_STANDARD 11)

# Specifies a path to native header files.
include_directories(
            ../cpp
            ../my-static-lib-headers
)
add_library(my-static-lib STATIC IMPORTED)
set_target_properties(my-static-lib PROPERTIES IMPORTED_LOCATION "${CMAKE_SOURCE_DIR}/static/lib/path")

add_library(cpp
            SHARED
            ../cpp/react-native-turbomodule-project.cpp
            cpp-adapter.cpp
)
target_link_libraries(cpp my-static-lib)

yarn android:

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':react-native-no-backwards:buildCMakeDebug[arm64-v8a]'.
> com.android.ide.common.process.ProcessException: ninja: Entering directory `/.../react-native-no-backwards/android/.cxx/Debug/1w152j5w/arm64-v8a'
  [1/1] Linking CXX shared library ../../../../build/intermediates/cxx/Debug/1w152j5w/obj/arm64-v8a/libcpp.so
  FAILED: ../../../../build/intermediates/cxx/Debug/1w152j5w/obj/arm64-v8a/libcpp.so 
  : && /.../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ --target=aarch64-none-linux-android21 --sysroot=/.../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot -fPIC -O2 -frtti -fexceptions -Wall -fstack-protector-all -g  -fno-limit-debug-info  -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--fatal-warnings -Qunused-arguments -Wl,--no-undefined -shared -Wl,-soname,libcpp.so -o ../../../../build/intermediates/cxx/Debug/1w152j5w/obj/arm64-v8a/libcpp.so CMakeFiles/cpp.dir/.../react-native-no-backwards/ffi/ifaddrs.cpp.o CMakeFiles/cpp.dir/.../react-native-no-backwards/cpp/react-native-no-backwards.cpp.o CMakeFiles/cpp.dir/cpp-adapter.cpp.o  ../../../../../ffi/arm64-v8a/libffi.a  /.../Library/Android/sdk/ndk/23.1.7779620/toolchains/llvm/prebuilt/darwin-x86_64/sysroot/usr/lib/aarch64-linux-android/21/liblog.so   -static-libstdc++ -latomic -lm && :
  ld: error: undefined symbol: stdout
  >>> referenced by sqlite3.c
  >>>               sqlite3.o:(sqlcipher_cipher_profile) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced by sqlite3.c
  >>>               sqlite3.o:(sqlcipher_cipher_profile) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced by sqlite3.c
  >>>               sqlite3.o:(sqlcipher_set_log) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced 1 more times
  
  ld: error: undefined symbol: stderr
  >>> referenced by sqlite3.c
  >>>               sqlite3.o:(sqlcipher_cipher_profile) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced by sqlite3.c
  >>>               sqlite3.o:(sqlcipher_cipher_profile) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced by sqlite3.c
  >>>               sqlite3.o:(sqlcipher_set_log) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced 31 more times
  
  ld: error: undefined symbol: stdin
  >>> referenced by ui_openssl.c
  >>>               ui_openssl.o:(open_console) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced by ui_openssl.c
  >>>               ui_openssl.o:(open_console) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced by ui_openssl.c
  >>>               ui_openssl.o:(close_console) in archive ../../../../../ffi/arm64-v8a/libffi.a
  >>> referenced 1 more times
  clang-12: error: linker command failed with exit code 1 (use -v to see invocation)
  ninja: build stopped: subcommand failed.

Solution

  • The stdout and related symbols are only in libc as of android API level 23, which was released 8 years ago.

    % for x in */libc.so; do nm $x | grep -q stdout && echo $x; done
    23/libc.so
    24/libc.so
    26/libc.so
    27/libc.so
    28/libc.so
    29/libc.so
    30/libc.so
    31/libc.so
    32/libc.so
    33/libc.so