hansgans
hansgans

Reputation: 337

CMake submodules dependencies

I have a CMake project with two submodules A and B. B depends on A. In submodule B I would like to search for A using find_package(A CONFIG). My minimal (not) working example would be:

CMakeLists.txt
   cmake_minimum_required(VERSION 3.13)
   project(AB)
   add_subdirectory(B)
   add_subdirectory(A)
A/CMakeLists.txt:
   message(STATUS "CMake: A")
   add_library(A SHARED A.hpp A.cpp)
   target_include_directories(A PUBLIC "${CURRENT_SOURCE_DIR}")
   install(TARGETS A EXPORT AA LIBRARY DESTINATION lib/)
   export(TARGETS A NAMESPACE AA:: FILE ${CMAKE_BINARY_DIR}/A/AConfig.cmake)
   export(PACKAGE AA)
A/A.hpp (some non-sense code)
A/A.cpp
B/CMakeLists.txt
   find_package(A CONFIG)
   message(STATUS "---> ${A_FOUND}")
   add_library(B B.hpp B.cpp)
   target_link_libraries(B AA::A)
B/B.hpp (some non-sense code)
B/B.cpp

A/CMakeList.txt correctly produces a AConfig.cmake. But as I understand it does that after(!) find_package(A CONFIG) is called and therefore AConfig.cmake is not found. Any idea how to force find_package() to run after A is executed?

Of course I know that in this example find_package does not make any sense. In my actual project the submodules are external software which I do not want to modify (in my case parallelSTL and TBB).

Upvotes: 3

Views: 1860

Answers (1)

hansgans
hansgans

Reputation: 337

Indeed cmake currently does not properly support this. A discussion for future plans can be found here. Here is my ugly workaround:

A/CMakeLists.txt:
   message(STATUS "CMake: A")
   add_library(A SHARED A.hpp A.cpp)
   target_include_directories(A PUBLIC "${CURRENT_SOURCE_DIR}")
   install(TARGETS A EXPORT AA LIBRARY DESTINATION lib/)
   export(TARGETS A NAMESPACE AA:: FILE ${CMAKE_BINARY_DIR}/A/AConfig.cmake)
   export(PACKAGE AA)

   add_library(AA::A ALIAS A)
   file(WRITE ${CMAKE_BINARY_DIR}/A/AConfig.cmake "")
   # include(CMakePackageConfigHelpers)
   # write_basic_package_version_file(
   #   ${CMAKE_BINARY_DIR}/A/AConfigVersion.cmake
   #   VERSION 1.0.0
   #   COMPATIBILITY AnyNewerVersion)

So the idea is to create a dummy file AConfig.cmake. This is overwritten later but it ensures that find_package() does not fail before it is actually created. Then we need to alias the target A to the name after the import AA::A. In case that there is a requirement on the version of A, than a file AConfigVersion.cmake needs to be created as well. I created a MWE on github.

Upvotes: 2

Related Questions