c++cmakereact-native-hermes

Which libraries are available to link in cmake?


I was learning CMake for a project and feel confused when linking libraries.

I find it easier to ask with an example, as using terms I am not familiar could be misleading.

The questions are (also commented in the example codes)

  1. how can I know what are the library name I can link to my target? Can I tell that from the build file structure, or I need to look into CMakeLists.txt of the external libraries. (e.g. the gtest-main and libhermes in the example)
  2. How can I use a "grandchild" library that is part of the external library? (e.g. the jsi library in the example)

Example

Let's say I am writing some tests with dependency on the Hermes Library. I then write a CMakeList.txt file like

cmake_minimum_required(VERSION 3.13)
project(mytests_cxx)

set(CMAKE_CXX_STANDARD 14)

include(FetchContent)

FetchContent_Declare(
  hermes
  URL https://github.com/facebook/hermes/archive/d63feeb46d26fe0ca7e789fc793f409e5158b27f.zip
)
FetchContent_MakeAvailable(hermes)

enable_testing()

add_executable(
  hello_test
  ./test.cpp
)

find_library (
  LIB_HERMES
  hermes # <- how can I know what is the name?
)


find_library (
  LIB_JSI
  jsi # <- How could I use a "grandchild" dependency, it is defined here (https://github.com/facebook/hermes/tree/main/API/jsi/jsi)
)

target_link_libraries(
  hello_test
  gtest_main <- Hermes seems to use gtest, how could make sure gtest_main is available?
  LIB_HERMES
  LIB_JSI
)

include(GoogleTest)
gtest_discover_tests(hello_test)

Running cmake to build

cmake -S . -B build -DHERMES_BUILD_SHARED_JSI=ON // I see an option defined in heremes'CMakeLists.txt but not sure if I am using it right.

the directory in build

tree ./build -L 2
./build
├── CMakeCache.txt
├── CMakeFiles
│   ├── 3.23.1
│   ├── CMakeDirectoryInformation.cmake
│   ├── CMakeError.log
│   ├── CMakeOutput.log
│   ├── CMakeRuleHashes.txt
│   ├── CMakeTmp
│   ├── Makefile.cmake
│   ├── Makefile2
│   ├── Progress
│   ├── TargetDirectories.txt
│   ├── cmake.check_cache
│   ├── hello_test.dir
│   └── progress.marks
├── CTestTestfile.cmake
├── ImportHermesc.cmake
├── Makefile
├── _deps
│   ├── hermes-build
│   ├── hermes-src
│   └── hermes-subbuild
├── bin
│   └── hermes-lit
├── cmake_install.cmake
├── compile_commands.json
└── hello_test[1]_include.cmake

then I run cmake --build build and see this error

/.../test.cpp:8:10: fatal error: 'jsi/jsi.h' file not found
#include <jsi/jsi.h>

Solution

  • Your question is too broad. Either ask a question about the list of libraries in cmake, or ask a question about how to compile and link with hermes, or ask a question about a specific problem with your build about including a third party. These should be 3 separate questions on this site.

    how can I know what are the library name I can link to my target?

    There are two things that you can target_link_libraries - you can link with libraries available on your system and link with targets defined in cmake.

    You can list libraries available on your system by traversing all paths outputted by ld --verbose and listing all lib*.so files in those directories. Or https://unix.stackexchange.com/questions/43187/how-do-i-get-a-list-of-shared-library-filenames-under-linux or similar. See man ld.so.

    You can list all targets defined in cmake. How do I list the defined make targets from the command line? .

    These lists combined consist of all possible libraries names that you can link with.

    Can I tell that from the build file structure

    I do not understand. No.

    I need to look into CMakeLists.txt of the external libraries

    Yes, usually you want to look into any external libraries CMakeLists.txt at least to check for malicious code.

    You usually look into documentation of external libraries. And, because source code is a form of documentation in open-source projects, you would look into the source code, yes.

    How can I use a "grandchild" library that is part of the external library?

    There are multiple ways for including external projects. Cases were outlined in Correct way to use third-party libraries in cmake project .

    That said, not all CMake projects work properly with add_subdirectory() (which is called by FetchContent_MakeAvailable) - there are many cases where the third-party projects CMakeLists.txt may not work with parent project. In such cases, I would go with compiling and installing the project into a subdirectory for example before running CMake or with ExternalProject_Add, and then only including the result of compilation with hand-crafted find_library and target_include_directories from the installation directory.

    Overall, including a third party is not always an easy task, and yes it requires you to become intimate with the specifics of a third party project and how it works and how it was written and decide how you want it to include in your project.