Modifying cmake file to create packageConfig.cmake and friends

I am working to support the use of find_package with a particular project.

I added a file called SmtpMimeConfig.cmake which reads:

include(CMakeFindDependencyMacro)
# find_dependency(xxx 2.0)
include(${CMAKE_CURRENT_LIST_DIR}/SmtpMimeTargets.cmake)

The end of the main cmake file used to read:

include(GNUInstallDirs)
install(TARGETS ${LIBRARY_TARGET_NAME}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/smtpmime
)

I’ve changed that to read:

include(GNUInstallDirs)
install(TARGETS ${LIBRARY_TARGET_NAME}
	EXPORT SmtpMimeTargets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/smtpmime
)
	
install(EXPORT SmtpMimeTargets
	NAMESPACE SmtpMime::
	DESTINATION lib/cmake/smtpmime 
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    "SmtpMimeConfigVersion.cmake"
    VERSION ${smtpmime_VERSION}
    COMPATIBILITY AnyNewerVersion)
	
install(FILES "SmtpMimeConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/SmtpMimeConfigVersion.cmake"
    DESTINATION lib/cmake/smtpmime)	

which appears to work, but could I have done that better/more tidily?

Thanks
David

You could have also generated the CMake config with configure_package_config_file() instead of writing it manually.

As for the being tidy, my installation module is even longer, but it doesn’t bother me at all. If that what it takes - so be it, I wouldn’t be considerably happier if I could do all that with less lines.

yes, you are right!

But be prepared to install FILE_SET HEADER and CXX_MODULES too.

1 Like

Could you give a specific example targeted to this case please? I much prefer simple solutions :slight_smile:

Please include the packageConfig.cmake.in in your example …

David

It is all part of the linked repository, is it not.

1 Like
if(ALGO_USE_MODULES)
  ##################################################
  add_library(Algo SHARED)
  add_library(my_package::Algo ALIAS Algo)
  target_sources(Algo PRIVATE algo-impl.cpp PUBLIC FILE_SET CXX_MODULES FILES algo-interface.cppm)

  # CMake requires the language standard to be specified as compile feature
  # when a target provides C++23 modules and the target will be installed
  target_compile_features(Algo PUBLIC cxx_std_23)

  if(CMAKE_CXX_MODULE_STD)
    target_compile_definitions(Algo PUBLIC HAS_IMPORT_STD)
  endif()

  # XXX target_link_libraries(Algo PUBLIC $<BUILD_INTERFACE:a4z::commonCompilerWarnings>)

  include(GenerateExportHeader)
  generate_export_header(Algo CUSTOM_CONTENT_FROM_VARIABLE)
  target_sources(
    Algo PUBLIC FILE_SET HEADERS BASE_DIRS ${CMAKE_CURRENT_BINARY_DIR} FILES
                ${CMAKE_CURRENT_BINARY_DIR}/algo_export.h
  )

  if(NOT CMAKE_SKIP_INSTALL_RULES)
    include(CPack)
    include(GNUInstallDirs)
    include(CMakePackageConfigHelpers)

    write_basic_package_version_file(
      "my_package-config-version.cmake" COMPATIBILITY SameMajorVersion
    )

    install(
      TARGETS Algo
      EXPORT my_package-targets
      # ... a few details omitted, see the "Deep CMake For Library Authors" talk
      FILE_SET CXX_MODULES
      # There's currently no convention for this location, see discussion below
      DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_package/src
      CXX_MODULES_BMI
      DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_package/bmi-${CMAKE_CXX_COMPILER_ID}_$<CONFIG>
      FILE_SET HEADERS
      DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} # Same as default, could be omitted
      INCLUDES
      DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
    )
    install(EXPORT my_package-targets DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_package
            CXX_MODULES_DIRECTORY . NAMESPACE my_package::
    )
    install(FILES "${PROJECT_BINARY_DIR}/my_package-config-version.cmake"
            DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_package
    )
    # The following file includes the my_package-targets.cmake file
    install(FILES cmake/my_package-config.cmake
            DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/my_package
    )
  endif()

  if(PROJECT_IS_TOP_LEVEL)
    enable_testing()
    add_subdirectory(example)
  endif()

  ##################################################
endif()

cmake/my_package-config:

# include(CMakeFindDependencyMacro)
# only if runtime dependency needed: i.e. find_dependency(fmt)

include("${CMAKE_CURRENT_LIST_DIR}/my_package-targets.cmake")