Kostya Vasilyev
Kostya Vasilyev

Reputation: 874

CMake issue linking to external project

I'm trying to add BoringSSL as a dependency of my library, using C++ with CMake for Android.

Here is what I'm doing:

add_library(mylib STATIC
    foo.cpp bar.cpp .....)

ExternalProject_Add(
        boringssl
        GIT_REPOSITORY "https://github.com/google/boringssl.git"
        GIT_TAG "origin/master"
        SOURCE_DIR "external/boringssl"
        STEP_TARGETS crypto ssl
        CMAKE_ARGS "-DOPENSSL_SMALL=TRUE"
)

add_dependencies(mylib boringssl)

target_link_directories(mylib PRIVATE
    "${CMAKE_CURRENT_BINARY_DIR}/external/boringssl/install/lib")
target_link_libraries(mylib PRIVATE
    crypto ssl)

The linker for "mylib" fails with "ld.lld: error: unable to find library -lcrypto" and "-lssl" and here is the weird thing:

Even though I use target_link_directories, the linker command line as printed out does not include the .../boringssl/install/lib directory. This directory doesn't exist at configure time (since ExternalProject_Add runs at build time) but that shouldn't be a problem, right?

I must be doing something wrong, what is it?

Broader question - I want to include BoringSSL as a dependency of my library, what's the best way to do it if not ExternalProject_Add ?


Edit: here is the linker command line, as you can see it's missing the link directory (my library is called srtc):

--target=aarch64-none-linux-android29 --sysroot=/mnt/android/sdk/ndk/27.2.12479018/toolchains/llvm/prebuilt/linux-x86_64/sysroot -fPIC -g -DANDROID -fdata-sections -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -D_FORTIFY_SOURCE=2 -Wformat -Werror=format-security  -fno-exceptions -fno-rtti -fno-limit-debug-info  -static-libstdc++ -Wl,--build-id=sha1 -Wl,--no-rosegment -Wl,--no-undefined-version -Wl,--fatal-warnings -Wl,--no-undefined -Qunused-arguments -shared -Wl,-soname,libsrtctest.so -o /home/kman/Android/proj-srtc/build/intermediates/cxx/Debug/5963472j/obj/arm64-v8a/libsrtctest.so CMakeFiles/srtctest.dir/jni_class_map.cpp.o CMakeFiles/srtctest.dir/jni_error.cpp.o CMakeFiles/srtctest.dir/jni_util.cpp.o CMakeFiles/srtctest.dir/jni_peer_connection.cpp.o CMakeFiles/srtctest.dir/srtctest_main.cpp.o  srtc/libsrtc.a  -landroid  -llog  -lcrypto  -lssl  -latomic -lm && :
  ld.lld: error: unable to find library -lcrypto
  ld.lld: error: unable to find library -lssl

Upvotes: 0

Views: 53

Answers (1)

AndrewBloom
AndrewBloom

Reputation: 2438

include(ExternalProject)
ExternalProject_Add(
        boringssl-build
        GIT_REPOSITORY "https://github.com/google/boringssl.git"
        GIT_TAG "origin/master"
        SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external/boringssl"
        BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/boringssl"
        STEP_TARGETS crypto ssl
        CMAKE_ARGS "-G Ninja"
                   "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}"
                   "-DANDROID_ABI=${ANDROID_ABI}"
                   "-DANDROID_PLATFORM=${ANDROID_PLATFORM}"
                   "-DBUILD_TYPE=Release"
                   "-DOPENSSL_SMALL=TRUE"
                   "-DBUILD_SHARED_LIBS=1"
        BUILD_BYPRODUCTS "${CMAKE_CURRENT_BINARY_DIR}/boringssl/libcrypto.so"
                         "${CMAKE_CURRENT_BINARY_DIR}/boringssl/libssl.so"
        BUILD_ALWAYS 1
)

add_library(crypto SHARED IMPORTED GLOBAL)
add_dependencies(crypto boringssl-build)

set_target_properties(crypto PROPERTIES
        IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/boringssl/libcrypto.so"
)

add_library(ssl SHARED IMPORTED GLOBAL)
add_dependencies(ssl boringssl-build)

set_target_properties(ssl PROPERTIES
        IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/boringssl/libssl.so"
)

# Specifies libraries CMake should link to your target library. You
# can link libraries from various origins, such as libraries defined in this
# build script, prebuilt third-party libraries, or Android system libraries.
target_link_libraries(${CMAKE_PROJECT_NAME}
        # List libraries link to the target library
        crypto ssl
        android
        log)

The code snippet is pretty explanatory, but let's stress some points:

  • Android is cross-compiled and ExternalProject_Add, as execute_process, spawn another independent instance of cmake. No arguments or variable are forwarded, so you need at least forward the toolchain file, the platform and the abi.
  • You most probably want always a release build type unless you plan to debug BoringSSL library.
  • I assumed you wanted shared libraries.
  • What makes the trick of triggering the build is BUILD_BYPRODUCTS
  • I don't see the point to use cmake to download the library through git, when you can do that using directly git and submodules. Here the point is that you want to download the source just once, so at least you need to specify a source dir instead of having it on the build directory that is architecture specific and is wiped out when cleaning the build.

Although the above works, IMO the better way to do that is:

add_subdirectory(external/boringssl)

with one line (given the source is at that location, for example taken as submodule) everything is taken care for you. The library is compiled by the same cmake process, and so you don't have to forward any arguments, this dodges a lot of trouble.

Upvotes: 0

Related Questions