Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cth_install_utilities.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,11 @@ function(_cth_add_pkg_target)
add_executable(${INSTALL_TARGET_NAME} ${PKG_DUMMY_SOURCE})
endif()

# a parent project that adds this project with add_subdirectory() does not install it on every build
if(NOT PROJECT_IS_TOP_LEVEL)
set_target_properties(${INSTALL_TARGET_NAME} PROPERTIES EXCLUDE_FROM_ALL TRUE)
endif()

# --- guard: packaging into the default install prefix is almost never intended ---
set(PKG_GUARD_SCRIPT "${CMAKE_BINARY_DIR}/_pkg_prefix_guard.cmake")
set(PKG_PREFIX_IS_DEFAULT FALSE)
Expand Down Expand Up @@ -668,6 +673,8 @@ endfunction()

.. note::
After calling this, build the ``${PROJECT_NAME}_package`` target to create the package.
Only the top level project builds it with ``all``, a parent project that adds this project with
``add_subdirectory()`` does not install it on every build.

.. note::
**Consumer usage:** ``find_package(${PROJECT_NAME} CONFIG REQUIRED COMPONENTS <comp>...)``
Expand Down
59 changes: 58 additions & 1 deletion cth_setup_utilities.cmake
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Copyright (c) 2026 Lukas Thomann
# Licensed under the MIT License

include(cth_assertions)

#[[.rst:
.. command:: cth_set_compiler_specifics

Expand Down Expand Up @@ -78,4 +80,59 @@ macro(cth_set_latest_c_cpp_standard)
set(CMAKE_CXX_EXTENSIONS OFF)

message("Set cxx standard to ${CMAKE_CXX_STANDARD}")
endmacro()
endmacro()

#[=[.rst:
.. command:: cth_add_subdirectory

.. code-block:: cmake

cth_add_subdirectory(<dir> [<option> [<default>]])

Adds a subdirectory, optionally behind an option. A parent project turns parts of a library off
by setting the options before it adds the library.

:param dir: Subdirectory to add, as for ``add_subdirectory()``
:type dir: path
:param option: Option that controls the subdirectory, omitted -> the subdirectory is always added
:type option: string
:param default: Value of the option if nothing sets it: ON, OFF or a variable name, evaluated with ``if()``
(default: ON)
:type default: boolean or variable name

:post: the subdirectory is added if ``option`` is ON or omitted

.. note::
Policy CMP0077 is NEW: a normal variable wins over the cache option,
``set(<option> OFF)`` before ``add_subdirectory(<library>)`` is enough.

.. note::
Pass a variable by name, ``WIN32`` instead of ``${WIN32}``: an undefined variable is OFF,
its empty expansion would drop the argument and leave the default ON.

#]=]
function(cth_add_subdirectory dir)
cth_assert_true(${ARGC} LESS_EQUAL 3 REASON "cth_add_subdirectory(<dir> [<option> [<default>]]), got: ${ARGV}")

if(ARGC EQUAL 1)
add_subdirectory("${dir}")
return()
endif()

set(option "${ARGV1}")
set(default ON)
if(ARGC EQUAL 3)
set(default OFF)
# unquoted: a variable name is dereferenced, an empty argument is OFF
if(NOT "${ARGV2}" STREQUAL "")
if(${ARGV2})
set(default ON)
endif()
endif()
endif()

option(${option} "add the ${dir} subdirectory" ${default})
if(${option})
add_subdirectory("${dir}")
endif()
endfunction()
15 changes: 15 additions & 0 deletions examples/basic/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,20 @@ target_include_directories(

target_link_libraries(basic_example_exec PRIVATE range-v3)


#optional subdirectories
cth_add_subdirectory(optional BASIC_EXAMPLE_OPTIONAL)
cth_assert_target(basic_example_optional REASON "cth_add_subdirectory must add a subdirectory that is ON")

set(BASIC_EXAMPLE_TRUE TRUE)
cth_add_subdirectory(enabled BASIC_EXAMPLE_ENABLED BASIC_EXAMPLE_TRUE)
cth_assert_target(basic_example_enabled REASON "cth_add_subdirectory must evaluate a variable default")

cth_add_subdirectory(unused BASIC_EXAMPLE_UNUSED_DEFAULT OFF)
cth_add_subdirectory(unused BASIC_EXAMPLE_UNUSED_UNDEFINED BASIC_EXAMPLE_UNDEFINED)

set(BASIC_EXAMPLE_UNUSED_SET OFF)
cth_add_subdirectory(unused BASIC_EXAMPLE_UNUSED_SET)

enable_testing()
add_test(NAME basic_example_exec COMMAND basic_example_exec)
1 change: 1 addition & 0 deletions examples/basic/enabled/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_library(basic_example_enabled INTERFACE)
1 change: 1 addition & 0 deletions examples/basic/optional/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_library(basic_example_optional INTERFACE)
1 change: 1 addition & 0 deletions examples/basic/unused/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
message(FATAL_ERROR "cth_add_subdirectory added a subdirectory that is OFF")
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ this is more or less for me, very handy but no backwards compatibility guarantee

- `cth_set_compiler_specifics`: apply compiler-specific common flags (MSVC vs others).
- `cth_set_latest_c_cpp_standard` (macro): prefer the newest supported C/C++ standard and set related policy/flags.
- `cth_add_subdirectory`: add a subdirectory behind an option (default ON, OFF or a variable like `WIN32`), a parent project turns parts of a library off with `set(<option> OFF)`.


## cth_tool_utilities
Expand Down
Loading