CMake and external dependency

2k Views Asked by At

I'd like to add an external dependency to my project. The one I'm trying to add is the Leptonica library as a submodule.

My project has the following directory structure:

|root
CMakeLists.txt
|-bin
|-build
|-buildsystem
|-executable
|-leptonica
|--CMakeLists.txt
|--cmake
|---Configure.cmake
|-production

In my root CMakeLists.txt file I added
ADD_SUBDIRECTORY(${ROOT_DIR}/leptonica)

Unfortunately, CMake is not searching for Configure.cmake in the proper directory:

CMake Error at leptonica/CMakeLists.txt:107 (include):

include could not find load file:

Configure

CMake Error: File

<root>/cmake/templates/LeptonicaConfig-version.cmake.in does not exist.

CMake Error at leptonica/CMakeLists.txt:113 (configure_file):

configure_file Problem configuring file

When I build the project by myself, everything goes fine. In my opinion, the problem is with CMAKE_SOURCE_DIR. When using add_subdirectory it has the value of ROOT CMake instead ROOT/leptonica, so it's searching the wrong paths - as you can see in Leptonica CMake, it's used to determinate paths of its files.

What should be the proper way to fix this - should I set CMAKE_SOURCE_DIR to ROOT/leptonica just before calling add_subdirectory and set it back when it's finished, or does some other, more elegant solutions exist?

2

There are 2 best solutions below

0
On BEST ANSWER

Not every CMake project is suitable for inclusion via add_subdirectory.

Among those are projects which uses CMAKE_SOURCE_DIR or CMAKE_BINARY_DIR variables.

However, inclusion via ExternalProject_Add (optionally wrapped with execute_process) always works.


Modifying variable CMAKE_SOURCE_DIR (and CMAKE_BINARY_DIR too) is a bad idea: this variable should be changed only by CMake itself. Otherwise you may get weird errors.

Instead, you may replace (automatically, with some script) all references to the variable with another variable, which is not used in the project. This new variable you may safely set before stepping into the subproject.

0
On

${CMAKE_SOURCE_DIR} and ${CMAKE_BINARY_DIR} are set relative to the top-level CMakeLists.txt. If you need something relative to your current CMakeLists.txt (leptonica), use ${CMAKE_CURRENT_SOURCE_DIR} and ${CMAKE_CURRENT_BINARY_DIR}.

If you're having trouble finding a cmake file like LeptonicaConfig-version.cmake.in, try appending the appropriate directory to ${CMAKE_MODULE_DIR}.

list(APPEND ${CMAKE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake/templates)

I prefer to use ${CMAKE_CURRENT_SOURCE_DIR} over ${CMAKE_SOURCE_DIR} any day because using the latter will break your build if you try to integrate it into a super-build later. If I need to pass my current top-level directory to subdirectories, then I do the following and use that later down the chain.

set( LEPTONICA_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} )