FetchContent - Automatically packaging needed files

I’m tring to package files needed to compile a sub library in my project. The project is a collection of multiple libraries and i would like to let users use all of them or pick only the one they need through FetchContent.

right now, I’m listing all the files by hand by doing something like:

set(mylib_pkg
  ${CMAKE_SOURCE_DIR}/CMakeLists.txt
  ${CMAKE_SOURCE_DIR}/src/CMakeLists.txt
  ${CMAKE_SOURCE_DIR}/src/fp
  ${CMAKE_SOURCE_DIR}/src/binary_search_tree
  ${CMAKE_SOURCE_DIR}/include
)
set(mylib_pkg_output ${CMAKE_LIBRARY_PACKAGE_OUTPUT_DIRECTORY}/mylib-pkg.zip)

add_custom_command(
  OUTPUT ${mylib_pkg_output}
  COMMAND ${CMAKE_COMMAND} -E tar c ${mylib_pkg_output} --format=zip -- ${mylib_pkg}
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  DEPENDS ${mylib_pkg})
add_custom_target(mylib_package DEPENDS ${mylib_pkg_output})

This works pretty well but I’m worried that it will not scale. Currently, I need to think about all the files needed and then I need test the compilation.

So, I’m wondering if there is a way to list all the files needed to compile a target and its dependencies (transitive or direct).

Why not pretty install your packages and the user may select what he need?

Or an other way, use CPM.cmake to build what you need as subproject.

I.e.: see GitHub - ClausKlein/boost-cmake: Easy Boost integration in CMake projects

Thank you for you answer. I want to be able to provide these sub-libraries for use with Fetchcontent. I also let them install the libraries if they need but most of the time i guess they will like to add it by simply fetching it. My current idea is based on this blog.

I check your link and CPM.make, however I’m not sure I understand how it works. It still looks like you mentioning all the files by hand. Not sure though, let me know if I’m wrong.

could I do something like this:

function(target_package tgt_name)
  set(_input_link_libraries LINK_LIBRARIES)
  set(_input_source_dir     SOURCE_DIR)
  set(_input_include_dir    INCLUDE_DIRECTORIES)

  get_target_property(_source_dir  ${tgt_name} ${_input_source_dir})
  get_target_property(_include_dir ${tgt_name} ${_input_include_dir})

  message(STATUS "ADD ${tgt_name}: ${_source_dir};${_include_dir}")
  list(APPEND source_dirs ${_source_dir} ${_include_dir})

  function(_recursively_collect_dependencies input_target)
    get_target_property(dependencies ${input_target} ${_input_link_libraries})

    foreach(dependency IN LISTS dependencies)
      get_target_property(_source_dir ${dependency} ${_input_source_dir})
      get_target_property(_include_dir ${dependency} ${_input_include_dir})

      message(STATUS "ADD ${dependency}: ${_source_dir};${_include_dir}")
      list(APPEND source_dirs ${_source_dir} ${_include_dir})
    endforeach()
    set(source_dirs ${source_dirs} PARENT_SCOPE)
  endfunction()

  _recursively_collect_dependencies(${tgt_name})

  message(STATUS "PKG ${tgt_name}: ${source_dirs}")
  add_custom_command(
    OUTPUT ${pkg_output_path}
    COMMAND ${CMAKE_COMMAND} -E tar c ${pkg_output_path} --format=zip -- ${source_dirs}
    WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
    DEPENDS ${source_dirs})
endfunction()

Is there some limitations to what I could access from a target ?

I would not work in this way!

You will lost any subproject compile and link option, i.e.:

  target_compile_definitions(
    boost
    INTERFACE $<$<CONFIG:Release>:BOOST_DISABLE_ASSERT>
              BOOST_ASIO_NO_DEPRECATED
              BOOST_SYSTEM_NO_DEPRECATED
              BOOST_THREAD_VERSION=5
              BOOST_THREAD_USES_CHRONO
              BOOST_THREAD_PROVIDES_EXECUTORS
  )
  add_library(Boost::asio ALIAS boost)
  target_link_libraries(boost INTERFACE Threads::Threads)

Divide and conquer and it will scale!

If I need the header only lib from boost, only this is needed and will bee compiled: boost-cmake/header.cmake at feature/bump-to-boost-v1.80.0 · ClausKlein/boost-cmake · GitHub

Even with COMPILE_OPTIONS and COMPILE_DEFINTIONS?

I do get your idea, but I really don’t know where to start and I really don’t what to do trials and error to get the right files that I need to include…