BinaryTarget

Operations to fully create and configure a C++ binary target. It greatly simplifies the most common process of creating an executable or library, by wrapping calls to CMake functions in higher-level functions. However, for more complex cases, you will need to use CMake's native commands. It requires CMake 4.0.1 or newer.

Synopsis

binary_target(CREATE <target-name> <STATIC|SHARED|HEADER|EXEC>)
binary_target(CONFIGURE_SETTINGS <target-name> [...])
binary_target(ADD_SOURCES <target-name> [...])
binary_target(ADD_PRECOMPILE_HEADER <target-name> HEADER_FILE <file-path>)
binary_target(ADD_INCLUDE_DIRECTORIES <target-name> PRIVATE [<dir-path>...|<gen-expr>...])
binary_target(ADD_LINK_LIBRARIES <target-name> PUBLIC [<target-name>...|<gen-expr>...])
binary_target(CREATE_FULLY <target-name> [...])

Usage

binary_target(CREATE <target-name> <STATIC|SHARED|HEADER|EXEC>)

Create a binary target named <PROJECT_NAME>_<target-name> and add it to the current CMake project, according to the specified binary type: STATIC , SHARED, HEADER, EXEC. Note that the logical name of the target <target-name> is prefixed with <PROJECT_NAME>_ in order to follow best practices. That is also why an aliased target is created with the name <PROJECT_NAME>::<target-name>, and the target properties OUTPUT_NAME and EXPORT_NAME are set to <target-name>.

A STATIC library forces BUILD_SHARED_LIBS to off and a SHARED library sets visibility and export-related variables before creating the target:

  • BUILD_SHARED_LIBS is set to on.

  • CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS is set to off to disable automatic symbol exports on Windows.

  • CMAKE_CXX_VISIBILITY_PRESET is set to hidden to hide symbols by default.

  • CMAKE_VISIBILITY_INLINES_HIDDEN is set to on so that inline symbols follow the same visibility rules.

Example usage:

binary_target(CREATE "my_static_lib" STATIC)
binary_target(CREATE "my_shared_lib" SHARED)
binary_target(CONFIGURE_SETTINGS <target-name> [...])

Configure settings for an existing binary target:

binary_target(CONFIGURE_SETTINGS <target-name>
             COMPILE_FEATURES [<feature>...]
             COMPILE_DEFINITIONS [<definition>...]
             COMPILE_OPTIONS [<option>...]
             LINK_OPTIONS [<option>...])

This command updates compile and link settings of a previously created target <target-name> with PRIVATE visibility. The following configuration options are supported:

The command automatically adds compile feature cxx_std_<CMAKE_CXX_STANDARD> to the target to set the CXX_STANDARD property, using the value of CMAKE_CXX_STANDARD. However, to avoid unnecessary duplication, it first checks whether the compile feature is already assigned to the target or in the arguments. An error is raised if CMAKE_CXX_STANDARD is not defined.

The target is also assigned to a default folder for improved IDE integration. All options are optional and may appear in any order. If a section is missing, it is simply ignored without warning.

This command is intended for targets that have been previously created using binary_target(CREATE).

Example usage:

binary_target(CREATE "my_shared_lib" SHARED)
binary_target(CONFIGURE_SETTINGS "<PROJECT_NAME>_my_shared_lib"
  COMPILE_FEATURES "cxx_std_20" "cxx_thread_local" "cxx_trailing_return_types"
  COMPILE_DEFINITIONS "DEFINE_ONE=1" "DEFINE_TWO=2" "OPTION_1"
  COMPILE_OPTIONS "-Wall" "-Wextra"
  LINK_OPTIONS "-s" "-z"
)
binary_target(ADD_SOURCES <target-name> [...])

Add source and header files to an existing binary target:

binary_target(ADD_SOURCES <target-name>
             SOURCE_FILES [<file-path>...]
             PRIVATE_HEADER_FILES [<file-path>...]
             PUBLIC_HEADER_FILES [<file-path>...])

Assigns implementation and header files to the given binary target <target-name> with PRIVATE visibility:

  • SOURCE_FILES: A list of source files (e.g., .cpp, .c) typically located in the src/ directory.

  • PRIVATE_HEADER_FILES: A list of private headers (e.g., .h) typically located in the src/ directory.

  • PUBLIC_HEADER_FILES: A list of public headers, usually found in an include/ directory.

These files are added to the target with target_sources() to populate the SOURCES target property. The command also defines a logical grouping of source files in IDEs (e.g., Visual Studio) using source_group(), based on the project's source tree.

This command is intended for targets that have been previously created using binary_target(CREATE), and is typically used in conjunction with directory(COLLECT_SOURCES_BY_POLICY) to get the required files.

Example usage:

binary_target(CREATE "my_static_lib" STATIC)
binary_target(ADD_SOURCES "<PROJECT_NAME>_my_static_lib"
  SOURCE_FILES "src/main.cpp" "src/util.cpp" "src/source_1.cpp"
  PRIVATE_HEADER_FILES "src/util.h" "src/source_1.h"
  PUBLIC_HEADER_FILES "include/lib_1.h" "include/lib_2.h"
)

# Or with `directory(COLLECT_SOURCES_BY_POLICY)`
binary_target(CREATE "my_static_lib" STATIC)
directory(COLLECT_SOURCES_BY_POLICY
  PUBLIC_HEADERS_SEPARATED true "${CMAKE_SOURCE_DIR}/include/mylib"
  PRIVATE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src"
  PRIVATE_SOURCE_FILES private_sources
  PUBLIC_HEADER_DIR public_header_dir
  PUBLIC_HEADER_FILES public_headers
  PRIVATE_HEADER_DIR private_header_dir
  PRIVATE_HEADER_FILES private_headers
)
binary_target(ADD_SOURCES "<PROJECT_NAME>_my_static_lib"
  SOURCE_FILES "${private_sources}"
  PRIVATE_HEADER_FILES "${private_headers}"
  PUBLIC_HEADER_FILES "${public_headers}"
)
binary_target(ADD_PRECOMPILE_HEADER <target-name> HEADER_FILE <file-path>)

Add a precompile header file (PCH) <file-path> to an existing binary target <target-name> with PRIVATE visibility.

This function is just a wrapper around target_precompile_headers() that populates the PRECOMPILE_HEADERS target property, so it follows the same specifications.

It is intended for targets that have been previously created using binary_target(CREATE).

Example usage:

binary_target(CREATE "my_static_lib" STATIC)
binary_target(ADD_PRECOMPILE_HEADER "<PROJECT_NAME>_my_static_lib"
  HEADER_FILE "src/header_pch.h"
)
binary_target(ADD_INCLUDE_DIRECTORIES <target-name> PRIVATE [<dir-path>...|<gen-expr>...])

Add include directories to an existing binary target <target-name> with PRIVATE visibility. The PRIVATE keyword is passed with the list of directory paths to add to <target-name>, or with generator expressions with the syntax $<...>. No checks are performed out on the nature and existence of the values associated with PRIVATE.

This function is just a wrapper around target_include_directories() that populates the INCLUDE_DIRECTORIES target property, so it follows the same specifications.

It is intended for targets that have been previously created using binary_target(CREATE), and is typically used in conjunction with directory(COLLECT_SOURCES_BY_POLICY) to get the required files.

Example usage:

binary_target(CREATE "my_static_lib" STATIC)
binary_target(ADD_INCLUDE_DIRECTORIES "my_static_lib"
  PRIVATE "include"
)

Add PUBLIC libraries to use when linking an existing binary target <target-name>. The PUBLIC keyword is passed with the list of names of other targets to link to <target-name>, or with generator expressions with the syntax $<...>.

This function is just a wrapper around target_link_libraries() that populates the LINK_LIBRARIES target property, so it follows the same specifications.

It is intended for targets that have been previously created using binary_target(CREATE).

Example usage:

# With target name
binary_target(CREATE "my_static_lib" STATIC)
binary_target(ADD_LINK_LIBRARIES "<PROJECT_NAME>_my_static_lib"
  PUBLIC "dep_1" "dep_2"
)

# With generator expression
binary_target(CREATE "my_static_lib" STATIC)
binary_target(ADD_LINK_LIBRARIES "<PROJECT_NAME>_my_static_lib"
  PUBLIC
    "$<BUILD_INTERFACE:dep_1;dep_2>"
    "$<INSTALL_INTERFACE:dep_1;dep_2>"
)
binary_target(CREATE_FULLY <target-name> [...])

Create a fully configured binary target:

binary_target(CREATE_FULLY <target-name>
              <STATIC|SHARED|HEADER|EXEC>
              [COMPILE_FEATURES <feature>...]
              [COMPILE_DEFINITIONS <definition>...]
              [COMPILE_OPTIONS <option>...]
              [LINK_OPTIONS <option>...]
              SOURCE_FILES [<file-path>...]
              PRIVATE_HEADER_FILES [<file-path>...]
              PUBLIC_HEADER_FILES [<file-path>...]
              [PRECOMPILE_HEADER_FILE <file-path>]
              INCLUDE_DIRECTORIES [<dir-path>...|<gen-expr>...]
              [LINK_LIBRARIES [<target-name>...|<gen-expr>...] ])

Create a fully configured binary target named <target-name> and add it to the current project. This command acts as a high-level wrapper that combines the behavior of other module sub-commands, including binary_target(CREATE), binary_target(CONFIGURE_SETTINGS), binary_target(ADD_SOURCES), binary_target(ADD_PRECOMPILE_HEADER), binary_target(ADD_INCLUDE_DIRECTORIES), and binary_target(ADD_LINK_LIBRARIES).

The second argument must specify the type of binary target to create: STATIC, SHARED, HEADER, or EXEC. Only one type may be given.

Additional parameters can be provided to configure compile options, precompiled headers, include directories, and target dependencies. Each of these keywords delegates internally to the corresponding BinaryTarget command. See their documentation for details.

Example usage:

directory(COLLECT_SOURCES_BY_POLICY
  PUBLIC_HEADERS_SEPARATED true "${CMAKE_SOURCE_DIR}/include/mylib"
  PRIVATE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src"
  PRIVATE_SOURCE_FILES private_sources
  PUBLIC_HEADER_DIR public_header_dir
  PUBLIC_HEADER_FILES public_headers
  PRIVATE_HEADER_DIR private_header_dir
  PRIVATE_HEADER_FILES private_headers
)
binary_target(
  CREATE_FULLY "my_shared_lib"
  SHARED
  COMPILE_FEATURES "cxx_std_20" "cxx_thread_local" "cxx_trailing_return_types"
  COMPILE_DEFINITIONS "DEFINE_ONE=1" "DEFINE_TWO=2" "OPTION_1"
  COMPILE_OPTIONS "-Wall" "-Wextra"
  LINK_OPTIONS "-s" "-z"
  SOURCE_FILES "${private_sources}"
  PRIVATE_HEADER_FILES "${private_headers}"
  PUBLIC_HEADER_FILES "${public_headers}"
  PRECOMPILE_HEADER_FILE "src/header_pch.h"
  INCLUDE_DIRECTORIES "$<$<BOOL:${private_header_dir}>:${private_header_dir}>" "${public_header_dir}"
  LINK_LIBRARIES "dep_1" "dep_2"
)

Full example

This example shows how to call the module functions to create a complete binary.

binary_target(CREATE "my_shared_lib" SHARED)
binary_target(CONFIGURE_SETTINGS "my_shared_lib"
  COMPILE_FEATURES "cxx_std_20" "cxx_thread_local" "cxx_trailing_return_types"
  COMPILE_DEFINITIONS "DEFINE_ONE=1" "DEFINE_TWO=2" "OPTION_1"
  COMPILE_OPTIONS "-Wall" "-Wextra"
  LINK_OPTIONS "-s" "-z"
)
directory(COLLECT_SOURCES_BY_POLICY
  PUBLIC_HEADERS_SEPARATED true "${CMAKE_SOURCE_DIR}/include/mylib"
  PRIVATE_SOURCE_DIR "${CMAKE_SOURCE_DIR}/src"
  PRIVATE_SOURCE_FILES private_sources
  PUBLIC_HEADER_DIR public_header_dir
  PUBLIC_HEADER_FILES public_headers
  PRIVATE_HEADER_DIR private_header_dir
  PRIVATE_HEADER_FILES private_headers
)
binary_target(ADD_SOURCES "my_shared_lib"
  SOURCE_FILES "${private_sources}"
  PRIVATE_HEADER_FILES "${private_headers}"
  PUBLIC_HEADER_FILES "${public_headers}"
)
binary_target(ADD_PRECOMPILE_HEADER "my_shared_lib"
  HEADER_FILE "src/header_pch.h"
)
binary_target(ADD_INCLUDE_DIRECTORIES "my_shared_lib"
  PRIVATE "$<$<BOOL:${private_header_dir}>:${private_header_dir}>" "${public_header_dir}"
)