1

For my project, I need to build and include another library, https://github.com/t-dillon/tdoku/, as my dependency.

Toku is also built using CMake, and there's a build script I can run by doing:

$ cd lib/toku
$ ./BUILD.sh

This puts the library file in ./lib/tdoku/build/libtdoku.a.

I'm trying to build the Toku library inside CMake, and use it as a dependency. How can I do this?

I tried using add_custom_target, add_custom_command, add_dependencies, add_subdirectory to no avail.

My current CMakeLists.txt looks like:

cmake_minimum_required(VERSION 3.17)
project(project_1_cpp)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wconversion")
set(CMAKE_CXX_FLAGS_DEBUG_INIT "")
set(CMAKE_CXX_FLAGS_RELEASE_INIT "-O3")

add_custom_target(toku)
add_custom_command(
  TARGET toku
  COMMAND ${CMAKE_SOURCE_DIR}/lib/tdoku/BUILD.sh
  WORKING_DIR ${CMAKE_SOURCE_DIR}/lib/tdoku
)

file(GLOB project_1_src "*.cpp")
add_executable(project_1_cpp ${project_1_src})
add_dependencies(tdoku project_1_cpp)
target_link_libraries(project_1_cpp ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a)
simonzack
  • 19,729
  • 13
  • 73
  • 118
  • Why so many people tend to use `add_custom_command(TARGET)` flow? This command flow is for some **specific cases**. In normal cases, if you know the output of `COMMAND`, then place it into `add_custom_command(OUTPUT)` flow. Otherwise, place it directly into `add_custom_target` call. Not sure what do you want to achieve by `add_dependencies(tdoku project_1_cpp)` call, but if you want express that "For build my `project_1_cpp` executable `toku` target should already be built", use `add_dependencies(project_1_cpp toku)`. – Tsyvarev Sep 05 '20 at 12:00
  • @Tsyvarev I'm not really sure what I'm doing. I tried using `add_custom_command` instead. I'm now getting `The dependency target ".../libtdoku.a" of target "project_1_cpp" does not exist.` – simonzack Sep 05 '20 at 12:42
  • Hmm I got the library compiling, but getting errors like `/usr/bin/ld: DWARF error: could not find variable specification at offset b090`. – simonzack Sep 05 '20 at 13:17

1 Answers1

2

From some help of @Tsyvarev, I first changed my CMakeLists.txt to include:

add_custom_command(
  OUTPUT ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a
  COMMAND ${CMAKE_SOURCE_DIR}/lib/tdoku/BUILD.sh tdoku
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/tdoku
)
add_custom_target(project DEPENDS ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a)

The key is that WORKING_DIR does not work, and I need to instead have WORKING_DIRECTORY. I figured this part out by trying to modify the build.sh script, and having it print things to a file, so I can know if it's being run at all, and what's breaking inside the script. I realized that the script's working directory was wrong.

In fact, I believe I did all this before posting the question, but I got the following errors after, which lead me to think that the tdoku library wasn't compiling properly. It was, but it was linking incorrectly to my project:

/usr/bin/ld: /usr/bin/ld: DWARF error: could not find variable specification at offset 223f
/usr/bin/ld: DWARF error: could not find variable specification at offset 22ba

I googled "DWARF error: could not find variable specification", which led me to ld.exe: DWARF error: could not find variable specification at offset 101cee. Googling cmake flto led me to How do I enable link time optimization (LTO) with CMake?.

This finally allowed me to compile my project.

The entire list of changes include:

set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)

add_custom_command(
  OUTPUT ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a
  COMMAND ${CMAKE_SOURCE_DIR}/lib/tdoku/BUILD.sh tdoku
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/lib/tdoku
)
add_custom_target(project DEPENDS ${CMAKE_SOURCE_DIR}/lib/tdoku/build/libtdoku.a)
simonzack
  • 19,729
  • 13
  • 73
  • 118