Skip to content

WIP: Add CMAKE_FIND_PACKAGE_INCLUDE variable

Ruslan Baratov requested to merge ruslo/cmake:wip.find-package-include into master

Introduce CMAKE_FIND_PACKAGE_INCLUDE variable that can be used for customization of find_package behavior without modifying user's CMake code.

Example:

cmake_minimum_required(VERSION 3.14)
project(app)

add_executable(app main.cpp)

find_package(foo CONFIG REQUIRED)
target_link_libraries(app PRIVATE foo::foo)

find_package(bar CONFIG REQUIRED)
target_link_libraries(app PRIVATE bar::bar)

System

By default packages will be found in system:

/usr/bin/g++
  CMakeFiles/app.dir/main.cpp.o
  -o app
  /usr/local/lib/libfoo.a
  /usr/local/lib/libbar.a 

ExternalProject

If packages installed by ExternalProject we can add CMAKE_PREFIX_PATH to specify the custom location:

/usr/bin/g++
  CMakeFiles/app.dir/main.cpp.o
  -o app
  /home/travis/__EP_root/lib/libfoo.a
  /home/travis/__EP_root/lib/libbar.a 

add_subdirectory

If the project structure is:

CMakeLists.txt
third_party/foo/CMakeLists.txt
third_party/bar/CMakeLists.txt

You can add next CMake hook:

# hooks/subdir.cmake

# create empty ${CMAKE_FIND_PACKAGE_NAME}Config.cmake for find_package
# <some code>

add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/${CMAKE_FIND_PACKAGE_NAME})

And use this hook by adding -DCMAKE_FIND_PACKAGE_INCLUDE=hooks/subdir.cmake without modifying original CMakeLists.txt:

/usr/bin/g++
  CMakeFiles/app.dir/main.cpp.o
  -o app
  third_party/foo/libfoo.a
  third_party/bar/libbar.a

Mix

If you want to take foo from add_subdirectory and other packages from ExternalProject:

# hooks/epsubdir.cmake

set(as_subproject foo)

if(NOT "${CMAKE_FIND_PACKAGE_NAME}" IN_LIST as_subproject)
  return()
endif()

# create empty ${CMAKE_FIND_PACKAGE_NAME}Config.cmake for find_package
# <some code>

add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/${CMAKE_FIND_PACKAGE_NAME})
/usr/bin/g++
  CMakeFiles/app.dir/main.cpp.o
  -o app
  third_party/foo/libfoo.a
  /home/travis/__EP_root/lib/libbar.a 

I.e., such approach can be used as a solution for #17735

FetchContent

Example of FetchContent hook:

# hooks/fetch.cmake

# create empty ${CMAKE_FIND_PACKAGE_NAME}Config.cmake for find_package
# <some code>

include(FetchContent)

FetchContent_Declare(
    ${CMAKE_FIND_PACKAGE_NAME}
    GIT_REPOSITORY https://github.com/.../${CMAKE_FIND_PACKAGE_NAME}.git
    GIT_TAG        v1.0.0
)

FetchContent_MakeAvailable(${CMAKE_FIND_PACKAGE_NAME})
/usr/bin/g++
  CMakeFiles/app.dir/main.cpp.o
  -o app
  _deps/foo-build/libfoo.a
  _deps/bar-build/libbar.a 

Hunter

Hook for Hunter:

# hooks/hunter.cmake

hunter_add_package(${CMAKE_FIND_PACKAGE_NAME})
/usr/bin/g++
  CMakeFiles/app.dir/main.cpp.o
  -o app
  /home/travis/.hunter/_Base/021aeb8/0ec0fcc/023562f/Install/lib/libfoo.a
  /home/travis/.hunter/_Base/021aeb8/0ec0fcc/023562f/Install/lib/libbar.a 

Test

Test for all the cases can be found here:

Results:

If it looks good, I can work on the rest of MR: documentation, tests, examples, etc.

Merge request reports