Crosspost: CMake Import/Export

I have created four example projects for demonstrating several aspects of import/export with cmake. Description is here: https://habla.news/u/purplekarrot.net/cmake-import-export

Most beman libraries are header only, but you may find some information useful nevertheless.

Definitely a few interesting points there:

Note that Qux does not set any value that begins with CMAKE_. Those variables are not meant to be set by projects. Setting them as cache variables would leak into the parent project, while setting them as non-cache variables would prevent injection from the parent project or from the packager.

This seems to be a fundamental point about cmake usage that is never been communicated clearly – although even clear communication about cmake has been obsoleted so it’s difficult to follow best practices. For Beman this should probably be in our guidelines.

Consider a C++ library that requires C++23 internally, but it has a C API, so C++23 is not a usage requirement.

I don’t think there’s anything in c++23 that would be abi incompatible with earlier versions – maybe contracts leaks in for 26, but I’m not even sure on that.

I see only c code? With CXX_MODULES there are also many points to know.

i.e.: C++20 Modules, CMake, And Shared Libraries - Crascit

And CXX_MODULES can’t be an interface library today!

see Linker error with CXX_MODULES - Development - CMake Discourse

That is not always true, i.e. from scope

# Modules opt in only on compilers that support it: msvc, g++-15 and clang-20+
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20)
    set(CMAKE_CXX_SCAN_FOR_MODULES 1)
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 15)
    set(CMAKE_CXX_SCAN_FOR_MODULES 1)
elseif(MSVC)
    set(CMAKE_CXX_SCAN_FOR_MODULES 1)
else()
    set(CMAKE_CXX_SCAN_FOR_MODULES 0)
endif()

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN TRUE)

or from Professional CMake book

  set(stageDir ${CMAKE_CURRENT_BINARY_DIR}/stage)
  include(GNUInstallDirs)
  if(NOT CMAKE_RUNTIME_OUTPUT_DIRECTORY)
      set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_BINDIR})
  endif()
  if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
      set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_LIBDIR})
  endif()
  if(NOT CMAKE_ARCHIVE_OUTPUT_DIRECTORY)
      set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${stageDir}/${CMAKE_INSTALL_LIBDIR})
  endif()


  if(PROJECT_IS_TOP_LEVEL)
      set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE)
      find_program(CLANG_TIDY_EXECUTABLE clang-tidy REQUIRED)
      find_program(RUN_CLANG_TIDY_EXECUTABLE run-clang-tidy REQUIRED)
      add_custom_target(run-clang-tidy
          COMMAND ${RUN_CLANG_TIDY_EXECUTABLE}
              -clang-tidy-binary ${CLANG_TIDY_EXECUTABLE}
              -p ${CMAKE_BINARY_DIR}
  ) 
  endif()

and

cmake_minimum_required(VERSION 3.21)
  project(coverage_example LANGUAGES CXX)
  enable_testing()
  if(PROJECT_IS_TOP_LEVEL AND CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
      set(CMAKE_CXX_FLAGS_COVERAGE "-g -O0 --coverage")
      if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
          string(APPEND CMAKE_CXX_FLAGS_COVERAGE " -fprofile-abs-path")
      endif()
      set(CMAKE_EXE_LINKER_FLAGS_COVERAGE "--coverage")
      set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE "--coverage")
      set(CMAKE_MODULE_LINKER_FLAGS_COVERAGE "--coverage")
  endif()
  add_subdirectory(src)