# Crosspost: CMake Import/Export

**URL:** https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513
**Category:** Beman Project Development
**Tags:** cmake, packaging
**Created:** [August 12, 2025, 2:36pm UTC](https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513 "2025-08-12T14:36:47Z")
**Posts on this page:** 5
**Page:** 1

<div class="post-metadata">

### Author: ![purpleKarrot](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/purplekarrot/32/127_2.png) [@purpleKarrot](https://discourse.bemanproject.org/u/purpleKarrot)
#### Post date: [August 12, 2025, 2:36pm UTC](https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513/1 "2025-08-12T14:36:47Z")

</div>

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](https://habla.news/u/purplekarrot.net/cmake-import-export)

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

---

<div class="post-metadata">

### Author: ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)
#### Post date: [August 16, 2025, 4:30pm UTC](https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513/2 "2025-08-16T16:30:50Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)
#### Post date: [January 16, 2026, 10:09pm UTC](https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513/3 "2026-01-16T22:09:22Z")

</div>

> [@purpleKarrot](#):
>
> [CMake Import/Export - Daniel Pfeifer](https://habla.news/u/purplekarrot.net/cmake-import-export)

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](https://crascit.com/2024/04/04/cxx-modules-cmake-shared-libraries/#h-linker-symbol-visibility)

And `CXX_MODULES` can’t be an interface library today!

see [Linker error with CXX\_MODULES - Development - CMake Discourse](https://discourse.cmake.org/t/linker-error-with-cxx-modules/15449)

---

<div class="post-metadata">

### Author: ![ClausKlein](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/clausklein/32/136_2.png) [@ClausKlein](https://discourse.bemanproject.org/u/ClausKlein)
#### Post date: [January 17, 2026, 8:32pm UTC](https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513/4 "2026-01-17T20:32:44Z")

</div>

> [@Jeff-Garland](#):
>
> 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.

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

```auto
# 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](https://crascit.com) book

```auto
  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

```auto
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)

```

---

<div class="post-metadata">

### Author: ![Jeff-Garland](https://yyz1.discourse-cdn.com/flex029/user_avatar/discourse.bemanproject.org/jeff-garland/32/23_2.png) [@Jeff-Garland](https://discourse.bemanproject.org/u/Jeff-Garland)
#### Post date: [February 16, 2026, 12:06am UTC](https://discourse.bemanproject.org/t/crosspost-cmake-import-export/513/5 "2026-02-16T00:06:26Z")

</div>

Yes – my comment in August was _me_ learning more about cmake best practices. Beman has taught me a lot about cmake I didn’t know.

Note that on my current project (and past ones for that matter) we violate these _guidelines_. In part because we didn’t realize and more importantly correctness and consistency requires the solution to be 100% in configuration management - reproducable without command options. We don’t want individual developers picking other C++ standards or whatever. It’s a completely opposite context to Beman an it’s goals.
