AddCA Module

A tenet of modern CMake is to avoid setting compiler flags manually, as they won’t work across all compilers and platforms unless guarded. Unfortunately due to the extensive range of toolchains which oneAPI Construction Kit supports utilizing bespoke compiler settings is unavoidable. We try to isolate all these platform specific configurations in the module cmake/AddCA.cmake using generator expressions to create variables for compiler options and definitions, set as CA_COMPILE_OPTIONS and CA_COMPILE_DEFINITIONS respectively.

See also

For guidance on when and why we use generator expressions see the Generator Expression Usage section.

AddCA.cmake then consumes these variables in the macros it exposes to wrap common CMake functions, such as add_ca_library(), add_ca_executable(), and add_ca_subdirectory(). These wrappers allow us to add the project wide compiler settings at a central location rather than scattered over the codebase, and to set target dependencies on any other targets which could be conditionally required to support our various CA build options for debugging and instrumentation.

The target_compile_options and target_compile_definitions CMake commands are the preferred way of adding flags in CMake, leading to the cleanest code by transitively passing on flags to dependent targets. Alternative add_compile_options is based on directory properties, and CMAKE_CXX_FLAGS is global and doesn’t work with generator expressions.

Our CA_COMPILE_OPTIONS and CA_COMPILE_DEFINITIONS variables are added to target_compile_options and target_compile_definitions using a PRIVATE scope, rather than PUBLIC or INTERFACE, meaning that the options won’t be propagated to any other targets which depend on the target we are modifing in the wrapper. This behavior is preferred over propagating the properties to the new target, where flags like -Werror could get set on linked application code which isn’t warning clean.

Argument Parsing

CMake provides the useful command cmake_parse_arguments, which facilitates complex argument parsing behaviors and is used to implement many of our add_ca prefixed helper functions in the AddCA.cmake module. We make use of it to parse single and multiple value keyword arguments, utilizing the first of the two available cmake_parse_arguments function signatures. This returns the parsed values as variables beginning with the parameterized prefix.

# Signature AddCA.cmake helper functions invoke
cmake_parse_arguments(<prefix> <options> <one_value_keywords>
                      <multi_value_keywords> <args>...)

A case study of this is our helper function add_ca_check(), generating check-ock and check-ock-<name> build targets used by continuous integration to verify a baseline of correctness. add_ca_check() takes a single positional argument name, for the target to generate a test for. A new testing target called check-ock-${name} is created from the name argument and a dependency on check-ock-${name} is added to the check target.

Additional add_ca_check() options to configure the testing target are parsed by forwarding on $ARGN arguments to cmake_parse_arguments via the <args> parameter, such as multi-value keyword COMMAND for defining the command to run for test invocation. NOENUMLATE and NOGLOBAL are also declared as flags via the <options> parameter, parsed as either TRUE or FALSE.

# Parse add_ca_check $ARGN arguments
cmake_parse_arguments(args
  "NOEMULATE;NOGLOBAL" "" "CLEAN;COMMAND;DEPENDS;ENVIRONMENT" ${ARGN})

After parsing is complete the results will available as variables prefixed with ‘args_’, e.g $args_COMMAND, for use in subsequent add_ca_check() logic.

Commands and Variables

AddCA.cmake exposes wrappers to common CMake functions, providing a single location to add ComputeAorta specific build options. These options may be platform dependent, or conditional on user provided build flags.

Using these add_ca* wrappers helps ensure that customer teams’ targets get built with the same options as ComputeAorta’s own targets.

To access the following commands and variables in this module:

include(AddCA)
CA_COMPILE_OPTIONS

Compile options to be added in ComputeAorta wrapper commands as PRIVATE target_compile_options for targets. Options are both platform and toolchain specific, and determined based on generator expressions.

CA_COMPILE_DEFINITIONS

Compile definitions to be added in ComputeAorta wrapper commands as PRIVATE target_compile_definitions for targets. Definitions are platform specific, and determined based on generator expressions.

CA_COMPILER_COMPILE_DEFINITIONS

Variable for propagating user options from root ComputeAorta CMakeLists.txt as PRIVATE compile definitions to be set using target_compile_definitions inside wrapper commands.

Options propagated as compile definitions:

  • CA_RUNTIME_COMPILER_ENABLED

  • CA_ENABLE_DEBUG_SUPPORT

  • CA_ENABLE_LLVM_OPTIONS_IN_RELEASE

add_ca_tidy

The add_ca_tidy() function creates a tidy target which invokes clang-tidy on every C or C++ file passed in. The first argument is assumed to be the target name. When an argument does not exist on the filesystem or is not a C or C++ file it is ignored, this allows passing the same list of arguments as add_ca_library() and add_ca_executable().

Arguments:
  • ARGV0 - Target name to tidy with tidy-${ARGV0}

  • ARGN - C/C++ files to tidy.

See also

This function consumes the CA_CLANG_TIDY_FLAGS user option.

set_ca_target_output_directory

The set_ca_target_output_directory() macro specifies the output directories for static or shared libraries and executables to consistent locations relative to the projects binary directory.

Arguments:
  • target - Named target to set output directory properties on.

add_ca_library

The add_ca_library() macro acts exactly like the default CMake add_library command except that it automatically adds project wide compiler options and definitions to the target.

add_ca_interface_library

The add_ca_interface_library() macro acts exactly like our add_ca_library() command except that it is specialised for INTERFACE libraries, such as header only libraries.

ca_target_link_options() acts like a simpler target_link_options from CMake 3.13+, but not in its full generality. Once the minimum required version is 3.13, we can swap out all uses for the builtin command. This command ensure the linker is called with flags for all build types. To specialize flags for a particular build configuration you must still set LINK_FLAGS_{RELEASE|MINSIZEREL|RELEASEASSERT} manually with set_target_properties, being mindful not to overwrite what is already there.

add_ca_executable

The add_ca_executable() macro acts exactly like the default CMake add_executable command except that it automatically adds project wide compiler options and definitions to the target.

target_ca_sources

The target_ca_sources macro acts exactly like the default CMake target_sources macro, but it also adds the source files to the tidy target as tidy-${target_name}.

Arguments:
  • target_name - Named target.

add_ca_subdirectory

The add_ca_subdirectory macro acts exactly like the default CMake add_subdirectory macro except that it automatically adds project wide compiler options and definitions to the target.

Arguments:
  • directory - Path of directory to add.

add_ca_example_subdirectory

The add_ca_example_subdirectory() function delays inclusion of a subdirectory containing targets relating to OpenCL examples until after those API source directories have been added to the CMake tree.

Arguments:
  • directory - Path to example directory.

Variables:

CA_EXAMPLE_DIRS

Internally cached variable holding a list of example source directories. Used by root ComputeAorta CMakeLists.txt as input to add_subdirectory once the API dependencies have been satisfied.

The get_target_link_libraries() macro queries, optionally recursively, the given targets link libraries. This is useful for checking the library dependencies of a target.

Arguments:
  • variable - The CMake variable name to store the result in.

  • target - The target to get the link libraries from.

Keyword Arguments:
  • RECURSIVE - Option to enable recursively getting the target link libraries.

get_ock_check_name

The get_ock_check_name function returns the name of a check target or group defined with the provided $name component. This naming scheme is used internally for naming all such targets and thus the final targets that users can ‘build’ to run tests.

Arguments:
  • check_name: The name of the output variable to set the check name.

  • name: The check name component

add_ca_check

The add_ca_check() macro takes a list of arguments which form a command to run a check. A new target is created and a dependency for that target is added to the project-level check target. The name of the new target is determined by calling the get_ock_check_name function on the parameter ${name}. To run an individual check build the specific target and to run all checks build the global check target. All checks are executed with a working directory of ${PROJECT_SOURCE_DIR} and a comment of the form “Running ${name} checks” is displayed by the build system during execution.

Note

If CA_ENABLE_TESTS is set to OFF this function does nothing.

Arguments:
  • name - Target name suffix for the check, this will create a target named via get_ock_check_name(target ${name}).

Keyword Arguments:
  • NOEMULATE - Flag to specify that the first argument of the COMMAND should not be emulated using CMAKE_CROSSCOMPILING_EMULATOR, this should be set if the executable driving the check is not cross-compiled.

  • NOGLOBAL - Flag to specify that the target check should not be added to the global check target.

  • GTEST - Flag to specify that this check uses GoogleTest and that CA_GTEST_LAUNCHER should be used, if set, to launch the check executable.

  • USES_TERMINAL - Flag to specify that the check will be given access to the terminal if possible.

  • COMMAND - Keyword after which one or more arguments should be specified to define the command the check target will execute.

  • CLEAN - Keyword after which one or more filenames should be listed as addition files to be clean up by the clean target.

  • DEPENDS - Keyword after which one or more target dependencies can be specified.

  • ENVIRONMENT - Keyword after which one or more environment variables can be specified, each must be of the form: “VAR=<value>”

add_ca_check_group

The add_ca_check_group() function creates a named target for a group of targets and/or checks, this is useful to setup check dependencies and for having a single named check for a set of disparate test suites. As with add_ca_check() the name is used to generate a target named by calling get_ock_check_name(target ${name}).

Note

If CA_ENABLE_TESTS is set to OFF this function does nothing.

Arguments:
  • name - Target name suffix for the check group, this will create a target named by calling get_ock_check_name(target ${name}).

Keyword Arguments:
  • NOGLOBAL - Flag to specify that the new target should not be added to the global check target.

  • DEPENDS - A list of targets this check group will depends on, any CMake target can be specified.

    Note

    The full target name including the global check prefix should be specified for dependent check targets.

Example:

add_ca_check_group(foo DEPENDS bar check-ock-foo)
add_ca_library_import

The add_ca_library_import() macro adds a target referring to an external library not produced as part of the ComputeAorta build.

Arguments:
  • target - Target name of library.

  • type - Type of library to be created in add_library, one of STATIC, SHARED, or MODULE.

  • location - Location on disk to set for the IMPORTED_LOCATION property.

add_ca_executable_import

The add_ca_executable_import() macro adds a target referring to an external executable not produced as part of the ComputeAorta build.

Arguments:
  • target - Target name of executable.

  • location - Location on disk to set for IMPORTED_LOCATION property.

add_ca_configure_file

The add_ca_configure_file() function adds a custom command which calls CMake’s builtin configure_file command at build time, this is useful when the only method of getting a path to a build target is by using generator expressions.

Arguments:
  • input - Input file configuration description.

  • output - Output file to be configured.

Keyword Arguments:
  • DEFINED - Specify a list of definitions taking the form “VAR=${value}” these will then be passed to to CMake’s script mode as -DVAR=${value}.

  • DEPENDS - Specify a list of dependencies.

Here’s an example:

add_ca_configure_file(path/to/input path/to/output
  DEFINED TARGET_EXECUTABLE=$<TARGET_FILE:target>
  DEPENDS target)
add_ca_copy_file

This function creates a custom command to copy an input file (usually in the source directory) to the output file (usually in the binary directory). It’s effectively a simpler version of add_ca_configure_file(), as it does not process the file in any way.

Keyword Arguments:
  • INPUT - The input file

  • OUTPUT - The output file

add_ca_cl_runtime_extension

The add_ca_cl_runtime_extension() function adds a set of runtime extensions to the OpenCL library build.

Arguments:
  • tag - Unique name for this set of extensions, it is used for accessing the extension information later in the build, must be a valid CMake variable name.

Keyword Arguments:
  • EXTENSIONS - List of OpenCL extension names to be added.

  • HEADER - Public OpenCL extension header to be installed.

  • INCLUDE_DIRS - List of include directories required to build the extensions.

  • SOURCES - List of source files required to build the extensions.

Variables:
CA_CL_RUNTIME_EXTENSION_TAGS

${tag} is appended to the list, then is internally cached.

${tag}_RUNTIME_EXTENSIONS

Internally cached list of ${tag} extensions.

${tag}_RUNTIME_HEADER

Internally cached extension header for ${tag} extensions.

${tag}_RUNTIME_INCLUDE_DIRS

Internally cached include directory for ${tag} extensions.

${tag}_RUNTIME_SOURCES

Internally cached List of source files for ${tag} extensions.

add_ca_cl_compiler_extension

The add_ca_cl_compiler_extension() function adds a set of compiler extensions to the OpenCL library build.

Arguments:
  • tag - Unique name for this set of extensions, it is used to make accessing the other information later in the build and must be a valid CMake variable name.

Keyword Arguments:
  • EXTENSIONS - List of OpenCL extension names to be added.

  • HEADER - Public OpenCL extension header to be installed.

  • INCLUDE_DIRS - List of include directories required to build the extensions.

  • SOURCES - List of source files required to build the extensions.

Variables:
CA_CL_COMPILER_EXTENSION_TAGS

${tag} is appended to the list, then internally cached.

${tag}_COMPILER_EXTENSIONS

Internally cached list of ${tag} compiler extensions.

${tag}_COMPILER_HEADER

Internally cached extension header for ${tag} extensions.

${tag}_COMPILER_INCLUDE_DIRS

Internally cached include directory for ${tag} extensions.

${tag}_COMPILER_SOURCES

Internally cached list of source files for ${tag} extensions.

add_ca_install_components

The add_ca_install_components() function creates a custom install target that will install all the specified components in the specified install directory.

Arguments:
  • ARGN - Target name for custom install target.

Keyword Arguments:
  • INSTALL_DIR - Directory to set for CMAKE_INSTALL_PREFIX.

  • COMPONENTS - One of more components to set for CMAKE_INSTALL_COMPONENT.

  • DEPENDS - One or more target dependencies.

For example to install only the OpenCL library and clVectorAddition in a directory called pkg:

add_ca_install_components(install-cl-clVectorAdd
  INSTALL_DIR ${CMAKE_BINARY_DIR}/pkg
  COMPONENTS OCL OCLExamples
  DEPENDS CL clVectorAddition)
add_ca_force_header

The add_ca_force_header() function adds a per-device force-header into the CA build.

Keyword Arguments:
  • PREFIX - A unique prefix for the internally generated files and variables

  • DEVICE_NAME - The name of the core device.

    Important

    DEVICE_NAME must match device_name from add_core_target in modules/core/source/CMakeLists.txt.

    Todo

    Create generated documentation for add_core_target to reference in above admonishment. JIRA CA-2757.

  • PATH - The file path of the force-include header

add_ca_configure_lit_site_cfg

This function provides an automatic way to ‘configure’-like generate a file based on a set of common and custom variables, specifically targeting the variables needed for the ‘lit.site.cfg’ files. This function bundles the common variables that any Lit instance is likely to need, and custom variables can be passed in.

On success, a custom target called name-lit will be created. This function may fail if certain required key LLVM tool components are not found, in which case the custom target will not have been created.

Note

Copied and stripped down from LLVM’s configure_lit_site_cfg, found in AddLLVM.cmake.

Arguments:
  • name - The name of the test suite.

  • site_in - The input path to the lit.site.cfg.in-like file

  • site_out - The output path to the generated lit.site.cfg file

Keyword Arguments:
  • MAIN_CONFIG - Path to the main lit.cfg to load. Can be empty, in which case a lit.cfg sourced from the same directory as site_in is used.

  • DEFINED - Extra defines, passed to add_ca_configure_file.

  • PATHS - The keyword PATHS is followed by a list of cmake variable names that are mentioned as path(“@varname@”) in the lit.cfg.py.in file. Variables in that list are treated as paths that are relative to the directory the generated lit.cfg.py file is in, and the path() function converts the relative path back to absolute form. This makes it possible to move a build directory containing lit.cfg.py files from one machine to another.

add_ca_lit_check

The add_ca_lit_check(target comment) raw function provides an automatic way to set up a check target to run a suite of LIT tests. Note that users are advised to use add_ca_lit_testsuite instead.

Arguments:
  • target - Named target to set output directory properties on. A target named by calling get_ock_check_name(check_target ${target}-lit) will be created which runs LIT tests producing XML results in ${target}-lit.xml.

  • comment - A comment to display to the terminal when running the check target.

Keyword Arguments:
  • NOGLOBAL - Flag to specify that the new target should not be added to the global check target.

  • PARAMS - Keyword after which one or more additional parameters to the llvm-lit command can be specified. Each parameter is automatically prepended with –param.

  • DEPENDS - Keyword after which one or more target dependencies can be specified.

  • ARGS - Keyword after which one or more arguments to the llvm-lit command can be specified.

add_ca_lit_testsuite

The add_ca_lit_testsuite(name) function creates a new lit test suite. A new target, named by calling get_ock_check_name(target ${name}-lit), is created and a dependency for that new target is added to the global check target. To run an individual check build the new target and to run all checks build the global check target. All checks are executed with a working directory of ${PROJECT_SOURCE_DIR} and a comment of the form “Running ${name} checks” is displayed by the build system during execution.

If EXCLUDE_FROM_UMBRELLAS is not set, the test suite will also be added to all open umbrella targets (see ca_umbrella_lit_testsuite_open() and ca_umbrella_lit_testsuite_close()).

Arguments:
  • name - Target name suffix for the check, this will create a target named as described above.

Keyword Arguments:
  • NOGLOBAL - Flag to specify that the new target should not be added to the global check target.

  • EXCLUDE_FROM_UMBRELLAS - Flag to specify that ${name} should not be added to any currently open test-suite umbrellas.

  • TARGET - Keyword after which a target name can be specified. If set, the test suite will be appended to a global set of test suites relating to that target. A global target will be created, comprised of all test suites relating to target. Has no effect if EXCLUDE_FROM_UMBRELLAS is set.

  • PARAMS - Keyword after which one or more additional parameters to the llvm-lit command can be specified. Each parameter is automatically prepended with –param.

  • DEPENDS - Keyword after which one or more target dependencies can be specified.

  • ARGS - Keyword after which one or more arguments to the llvm-lit command can be specified.

ca_umbrella_lit_testsuite_open

The ca_umbrella_lit_testsuite_open(target) function opens a new umbrella lit test suite.

All subsequent calls to add_ca_lit_testsuite (which don’t pass EXCLUDE_FROM_UMBRELLAS) are implicitly added to this umbrella suite. The umbrella suite is open until a corresponding call to ca_umbrella_lit_testsuite_close is made with the same target.

For example, given:

ca_umbrella_lit_testsuite_open(all)

*  add_ca_lit_testsuite(foo)

*  ca_umbrella_lit_testsuite_open(compiler)

*  - add_ca_lit_testsuite(bar)

*  - add_ca_lit_testsuite(baz)

*  - add_ca_lit_testsuite(special EXCLUDE_FROM_UMBRELLAS)

*  ca_umbrella_lit_testsuite_close(compiler)

ca_umbrella_lit_testsuite_close(all)

Produces the following check targets, from most outermost to innermost:

check-ock-all-lit:      foo, bar, baz

check-ock-compiler-lit: bar, baz

check-ock-foo-lit:      foo

check-ock-bar-lit:      bar

check-ock-baz-lit:      baz

check-ock-special-lit:  special

ca_umbrella_lit_testsuite_close

The ca_umbrella_lit_testsuite_close(target) function closes an open umbrella lit test suite.

A new check target named by calling get_ock_check_name(check_target ${target}-lit) will be created using test suites previously registered with add_ca_lit_testsuite while the umbrella was open.

See ca_umbrella_lit_testsuite_open for more details.