LIVE / thrust /dependencies /cub /cmake /CubBuildTargetList.cmake
Xu Ma
update
1c3c0d9
raw
history blame
9.06 kB
# This file provides utilities for building and working with CUB
# configuration targets.
#
# CUB_TARGETS
# - Built by the calling the `cub_build_target_list()` function.
# - Each item is the name of a CUB interface target that is configured for a
# certain build configuration. Currently only C++ standard dialect is
# considered.
#
# cub_build_target_list()
# - Creates the CUB_TARGETS list.
#
# The following functions can be used to test/set metadata on a CUB target:
#
# cub_get_target_property(<prop_var> <target_name> <prop>)
# - Checks the ${prop} target property on CUB target ${target_name}
# and sets the ${prop_var} variable in the caller's scope.
# - <prop_var> is any valid cmake identifier.
# - <target_name> is the name of a CUB target.
# - <prop> is one of the following:
# - DIALECT: The C++ dialect. Valid values: 11, 14, 17.
# - PREFIX: A unique prefix that should be used to name all
# targets/tests/examples that use this configuration.
#
# cub_get_target_properties(<target_name>)
# - Defines ${target_name}_${prop} in the caller's scope, for `prop` in:
# {DIALECT, PREFIX}. See above for details.
#
# cub_clone_target_properties(<dst_target> <src_target>)
# - Set the {DIALECT, PREFIX} metadata on ${dst_target} to match
# ${src_target}. See above for details.
# - This *MUST* be called on any targets that link to another CUB target
# to ensure that dialect information is updated correctly, e.g.
# `cub_clone_target_properties(${my_cub_test} ${some_cub_target})`
# Dialects:
set(CUB_CPP_DIALECT_OPTIONS
11 14 17
CACHE INTERNAL "C++ dialects supported by CUB." FORCE
)
define_property(TARGET PROPERTY _CUB_DIALECT
BRIEF_DOCS "A target's C++ dialect: 11, 14, or 17."
FULL_DOCS "A target's C++ dialect: 11, 14, or 17."
)
define_property(TARGET PROPERTY _CUB_PREFIX
BRIEF_DOCS "A prefix describing the config, eg. 'cub.cpp14'."
FULL_DOCS "A prefix describing the config, eg. 'cub.cpp14'."
)
function(cub_set_target_properties target_name dialect prefix)
set_target_properties(${target_name}
PROPERTIES
_CUB_DIALECT ${dialect}
_CUB_PREFIX ${prefix}
)
get_target_property(type ${target_name} TYPE)
if (NOT ${type} STREQUAL "INTERFACE_LIBRARY")
set_target_properties(${target_name}
PROPERTIES
CXX_STANDARD ${dialect}
CUDA_STANDARD ${dialect}
ARCHIVE_OUTPUT_DIRECTORY "${CUB_LIBRARY_OUTPUT_DIR}"
LIBRARY_OUTPUT_DIRECTORY "${CUB_LIBRARY_OUTPUT_DIR}"
RUNTIME_OUTPUT_DIRECTORY "${CUB_EXECUTABLE_OUTPUT_DIR}"
)
# CMake still emits errors about empty CUDA_ARCHITECTURES when CMP0104
# is set to OLD. This suppresses the errors for good.
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18)
set_target_properties(${target_name}
PROPERTIES
CUDA_ARCHITECTURES OFF
)
endif()
endif()
endfunction()
# Get a cub property from a target and store it in var_name
# cub_get_target_property(<var_name> <target_name> [DIALECT|PREFIX]
macro(cub_get_target_property prop_var target_name prop)
get_property(${prop_var} TARGET ${target_name} PROPERTY _CUB_${prop})
endmacro()
# Defines the following string variables in the caller's scope:
# - ${target_name}_DIALECT
# - ${target_name}_PREFIX
macro(cub_get_target_properties target_name)
cub_get_target_property(${target_name}_DIALECT ${target_name} DIALECT)
cub_get_target_property(${target_name}_PREFIX ${target_name} PREFIX)
endmacro()
# Set one target's _CUB_* properties to match another target
function(cub_clone_target_properties dst_target src_target)
cub_get_target_properties(${src_target})
cub_set_target_properties(${dst_target}
${${src_target}_DIALECT}
${${src_target}_PREFIX}
)
endfunction()
# Set ${var_name} to TRUE or FALSE in the caller's scope
function(_cub_is_config_valid var_name dialect)
if (CUB_ENABLE_DIALECT_CPP${dialect})
set(${var_name} TRUE PARENT_SCOPE)
else()
set(${var_name} FALSE PARENT_SCOPE)
endif()
endfunction()
function(_cub_init_target_list)
set(CUB_TARGETS "" CACHE INTERNAL "" FORCE)
endfunction()
function(_cub_add_target_to_target_list target_name dialect prefix)
cub_set_target_properties(${target_name} ${dialect} ${prefix})
target_link_libraries(${target_name} INTERFACE
CUB::CUB
cub.compiler_interface
)
if (TARGET cub.thrust)
target_link_libraries(${target_name} INTERFACE cub.thrust)
endif()
set(CUB_TARGETS ${CUB_TARGETS} ${target_name} CACHE INTERNAL "" FORCE)
set(label "cpp${dialect}")
string(TOLOWER "${label}" label)
message(STATUS "Enabling CUB configuration: ${label}")
endfunction()
# Build a ${CUB_TARGETS} list containing target names for all
# requested configurations
function(cub_build_target_list)
# Clear the list of targets:
_cub_init_target_list()
# Handle dialect options:
foreach (dialect IN LISTS CUB_CPP_DIALECT_OPTIONS)
if (CUB_IN_THRUST)
# Just use Thrust's settings:
if (THRUST_ENABLE_MULTICONFIG)
set(CUB_ENABLE_DIALECT_CPP${dialect}
${THRUST_MULTICONFIG_ENABLE_DIALECT_CPP${dialect}}
)
else()
set(val OFF)
if (dialect EQUAL ${THRUST_CPP_DIALECT})
set(val ON)
endif()
set(CUB_ENABLE_DIALECT_CPP${dialect} ${val})
endif()
else()
# Create CMake options:
set(default_value OFF)
if (dialect EQUAL 14) # Default to just 14 on:
set(default_value ON)
endif()
option(CUB_ENABLE_DIALECT_CPP${dialect}
"Generate C++${dialect} build configurations."
${default_value}
)
endif()
endforeach()
# CMake added C++17 support for CUDA targets in 3.18:
if (CUB_ENABLE_DIALECT_CPP17)
cmake_minimum_required(VERSION 3.18)
endif()
# Supported versions of MSVC do not distinguish between C++11 and C++14.
# Warn the user that they may be generating a ton of redundant targets.
if ("MSVC" STREQUAL "${CMAKE_CXX_COMPILER_ID}" AND
CUB_ENABLE_DIALECT_CPP11)
message(WARNING
"Supported versions of MSVC (2017+) do not distinguish between C++11 "
"and C++14. The requested C++11 targets will be built with C++14."
)
endif()
# Generic config flags:
macro(add_flag_option flag docstring default)
set(cub_opt "CUB_${flag}")
if (CUB_IN_THRUST)
set(thrust_opt "THRUST_${flag}")
# Use thrust's settings:
set(${cub_opt} ${${thrust_opt}})
else()
option(${cub_opt} "${docstring}" "${default}")
mark_as_advanced(${cub_opt})
endif()
endmacro()
add_flag_option(IGNORE_DEPRECATED_CPP_DIALECT "Don't warn about any deprecated C++ standards and compilers." OFF)
add_flag_option(IGNORE_DEPRECATED_CPP_11 "Don't warn about deprecated C++11." OFF)
add_flag_option(IGNORE_DEPRECATED_COMPILER "Don't warn about deprecated compilers." OFF)
# Build cub.compiler_interface with warning flags, etc
# This must be called before _cub_add_target_to_target_list.
cub_build_compiler_targets()
# Set up the CUB target while testing out our find_package scripts.
find_package(CUB REQUIRED CONFIG
NO_DEFAULT_PATH # Only check the explicit path in HINTS:
HINTS "${CUB_SOURCE_DIR}"
)
# TODO
# Some of the iterators and unittests depend on thrust. We should break the
# cyclical dependency by migrating CUB's Thrust bits into Thrust.
find_package(Thrust ${CUB_VERSION} EXACT CONFIG
HINTS "../../" # Check if we are in thrust/dependencies/cub
)
if (Thrust_FOUND)
thrust_set_CUB_target(CUB::CUB)
thrust_create_target(cub.thrust HOST CPP DEVICE CUDA)
else()
message(STATUS
"Thrust was not found. Set CMake variable 'Thrust_DIR' to the "
"thrust-config.cmake file of a Thrust ${CUB_VERSION} installation to "
"enable additional testing."
)
endif()
# Build CUB_TARGETS
foreach(dialect IN LISTS CUB_CPP_DIALECT_OPTIONS)
_cub_is_config_valid(config_valid ${dialect})
if (config_valid)
set(prefix "cub.cpp${dialect}")
string(TOLOWER "${prefix}" prefix)
set(target_name "${prefix}")
add_library(${target_name} INTERFACE)
# Set configuration metadata for this cub interface target:
_cub_add_target_to_target_list(${target_name} ${dialect} ${prefix})
endif()
endforeach() # dialects
list(LENGTH CUB_TARGETS count)
message(STATUS "${count} unique cub.dialect configurations generated")
# Top level meta-target. Makes it easier to just build CUB targets when
# building both CUB and Thrust. Add all project files here so IDEs will be
# aware of them. This will not generate build rules.
file(GLOB_RECURSE all_sources
RELATIVE "${CMAKE_CURRENT_LIST_DIR}"
"${CUB_SOURCE_DIR}/cub/*.cuh"
)
add_custom_target(cub.all SOURCES ${all_sources})
# Create meta targets for each config:
foreach(cub_target IN LISTS CUB_TARGETS)
cub_get_target_property(config_prefix ${cub_target} PREFIX)
add_custom_target(${config_prefix}.all)
add_dependencies(cub.all ${config_prefix}.all)
endforeach()
endfunction()