Files
clang-p2996/libclc/cmake/modules/AddLibclc.cmake
Michael Kruse 6838c7afb2 [libclc] Revise IDE folder structure (#89746)
Reviewers of #89153 suggested to break up the patch into per-subproject
patches. This is the libclc part. See #89153 for the entire series and
motivation.

Update the folder titles for targets in the monorepository that have not
seen taken care of for some time. These are the folders that targets are
organized in Visual Studio and XCode
(`set_property(TARGET <target> PROPERTY FOLDER "<title>")`)
when using the respective CMake's IDE generator.

 * Ensure that every target is in a folder
 * Use a folder hierarchy with each LLVM subproject as a top-level folder
 * Use consistent folder names between subprojects
 * When using target-creating functions from AddLLVM.cmake, automatically
deduce the folder. This reduces the number of
`set_property`/`set_target_property`, but are still necessary when
`add_custom_target`, `add_executable`, `add_library`, etc. are used. A
LLVM_SUBPROJECT_TITLE definition is used for that in each subproject's
root CMakeLists.txt.
2024-07-18 12:40:55 +02:00

181 lines
5.2 KiB
CMake

# Compiles an OpenCL C - or assembles an LL file - to bytecode
#
# Arguments:
# * TRIPLE <string>
# Target triple for which to compile the bytecode file.
# * INPUT <string>
# File to compile/assemble to bytecode
# * OUTPUT <string>
# Bytecode file to generate
# * EXTRA_OPTS <string> ...
# List of compiler options to use. Note that some are added by default.
# * DEPENDENCIES <string> ...
# List of extra dependencies to inject
#
# Depends on the clang, llvm-as, and llvm-link targets for compiling,
# assembling, and linking, respectively.
function(compile_to_bc)
cmake_parse_arguments(ARG
""
"TRIPLE;INPUT;OUTPUT"
"EXTRA_OPTS;DEPENDENCIES"
${ARGN}
)
# If this is an LLVM IR file (identified soley by its file suffix),
# pre-process it with clang to a temp file, then assemble that to bytecode.
set( TMP_SUFFIX )
get_filename_component( FILE_EXT ${ARG_INPUT} EXT )
if( NOT ${FILE_EXT} STREQUAL ".ll" )
# Pass '-c' when not running the preprocessor
set( PP_OPTS -c )
else()
set( PP_OPTS -E;-P )
set( TMP_SUFFIX .tmp )
endif()
set( TARGET_ARG )
if( ARG_TRIPLE )
set( TARGET_ARG "-target" ${ARG_TRIPLE} )
endif()
# Ensure the directory we are told to output to exists
get_filename_component( ARG_OUTPUT_DIR ${ARG_OUTPUT} DIRECTORY )
file( MAKE_DIRECTORY ${ARG_OUTPUT_DIR} )
add_custom_command(
OUTPUT ${ARG_OUTPUT}${TMP_SUFFIX}
COMMAND ${clang_exe}
${TARGET_ARG}
${PP_OPTS}
${ARG_EXTRA_OPTS}
-MD -MF ${ARG_OUTPUT}.d -MT ${ARG_OUTPUT}${TMP_SUFFIX}
# LLVM 13 enables standard includes by default - we don't want
# those when pre-processing IR. We disable it unconditionally.
$<$<VERSION_GREATER_EQUAL:${LLVM_PACKAGE_VERSION},13.0.0>:-cl-no-stdinc>
-emit-llvm
-o ${ARG_OUTPUT}${TMP_SUFFIX}
-x cl
${ARG_INPUT}
DEPENDS
${clang_target}
${ARG_INPUT}
${ARG_DEPENDENCIES}
DEPFILE ${ARG_OUTPUT}.d
)
if( ${FILE_EXT} STREQUAL ".ll" )
add_custom_command(
OUTPUT ${ARG_OUTPUT}
COMMAND ${llvm-as_exe} -o ${ARG_OUTPUT} ${ARG_OUTPUT}${TMP_SUFFIX}
DEPENDS ${llvm-as_target} ${ARG_OUTPUT}${TMP_SUFFIX}
)
endif()
endfunction()
# Links together one or more bytecode files
#
# Arguments:
# * TARGET <string>
# Custom target to create
# * INPUT <string> ...
# List of bytecode files to link together
# * DEPENDENCIES <string> ...
# List of extra dependencies to inject
function(link_bc)
cmake_parse_arguments(ARG
""
"TARGET"
"INPUTS;DEPENDENCIES"
${ARGN}
)
set( LINK_INPUT_ARG ${ARG_INPUTS} )
if( WIN32 OR CYGWIN )
# Create a response file in case the number of inputs exceeds command-line
# character limits on certain platforms.
file( TO_CMAKE_PATH ${LIBCLC_ARCH_OBJFILE_DIR}/${ARG_TARGET}.rsp RSP_FILE )
# Turn it into a space-separate list of input files
list( JOIN ARG_INPUTS " " RSP_INPUT )
file( WRITE ${RSP_FILE} ${RSP_INPUT} )
# Ensure that if this file is removed, we re-run CMake
set_property( DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS
${RSP_FILE}
)
set( LINK_INPUT_ARG "@${RSP_FILE}" )
endif()
add_custom_command(
OUTPUT ${ARG_TARGET}.bc
COMMAND ${llvm-link_exe} -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
DEPENDS ${llvm-link_target} ${ARG_DEPENDENCIES} ${ARG_INPUTS} ${RSP_FILE}
)
add_custom_target( ${ARG_TARGET} ALL DEPENDS ${ARG_TARGET}.bc )
set_target_properties( ${ARG_TARGET} PROPERTIES
TARGET_FILE ${ARG_TARGET}.bc
FOLDER "libclc/Device IR/Linking"
)
endfunction()
# Decomposes and returns variables based on a libclc triple and architecture
# combination. Returns data via one or more optional output variables.
#
# Arguments:
# * TRIPLE <string>
# libclc target triple to query
# * DEVICE <string>
# libclc device to query
#
# Optional Arguments:
# * CPU <var>
# Variable name to be set to the target CPU
# * ARCH_SUFFIX <var>
# Variable name to be set to the triple/architecture suffix
# * CLANG_TRIPLE <var>
# Variable name to be set to the normalized clang triple
function(get_libclc_device_info)
cmake_parse_arguments(ARG
""
"TRIPLE;DEVICE;CPU;ARCH_SUFFIX;CLANG_TRIPLE"
""
${ARGN}
)
if( NOT ARG_TRIPLE OR NOT ARG_DEVICE )
message( FATAL_ERROR "Must provide both TRIPLE and DEVICE" )
endif()
string( REPLACE "-" ";" TRIPLE ${ARG_TRIPLE} )
list( GET TRIPLE 0 ARCH )
# Some targets don't have a specific device architecture to target
if( ARG_DEVICE STREQUAL none OR ARCH STREQUAL spirv OR ARCH STREQUAL spirv64 )
set( cpu )
set( arch_suffix "${ARG_TRIPLE}" )
else()
set( cpu "${ARG_DEVICE}" )
set( arch_suffix "${ARG_DEVICE}-${ARG_TRIPLE}" )
endif()
if( ARG_CPU )
set( ${ARG_CPU} ${cpu} PARENT_SCOPE )
endif()
if( ARG_ARCH_SUFFIX )
set( ${ARG_ARCH_SUFFIX} ${arch_suffix} PARENT_SCOPE )
endif()
# Some libclc targets are not real clang triples: return their canonical
# triples.
if( ARCH STREQUAL spirv OR ARCH STREQUAL clspv )
set( ARG_TRIPLE "spir--" )
elseif( ARCH STREQUAL spirv64 OR ARCH STREQUAL clspv64 )
set( ARG_TRIPLE "spir64--" )
endif()
if( ARG_CLANG_TRIPLE )
set( ${ARG_CLANG_TRIPLE} ${ARG_TRIPLE} PARENT_SCOPE )
endif()
endfunction()