Files
clang-p2996/libclc/cmake/modules/AddLibclc.cmake
Fraser Cormack effb2f1917 [libclc] Use a response file when building on Windows (#89756)
We've recently seen the libclc llvm-link invocations become so long that
they exceed the character limits on certain platforms.

Using a 'response file' should solve this by offloading the list of
inputs into a separate file, and using special syntax to pass it to
llvm-link. Note that neither the response file nor syntax aren't
specific to Windows but we restrict it to that platform regardless. We
have the option of expanding it to other platforms in the future.
2024-04-24 10:11:26 +01:00

176 lines
5.0 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 libclc::clang and libclc::llvm-as targets for compiling and
# assembling, 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 libclc::clang
${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
libclc::clang
${ARG_INPUT}
${ARG_DEPENDENCIES}
DEPFILE ${ARG_OUTPUT}.d
)
if( ${FILE_EXT} STREQUAL ".ll" )
add_custom_command(
OUTPUT ${ARG_OUTPUT}
COMMAND libclc::llvm-as -o ${ARG_OUTPUT} ${ARG_OUTPUT}${TMP_SUFFIX}
DEPENDS libclc::llvm-as ${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
function(link_bc)
cmake_parse_arguments(ARG
""
"TARGET"
"INPUTS"
${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 libclc::llvm-link -o ${ARG_TARGET}.bc ${LINK_INPUT_ARG}
DEPENDS libclc::llvm-link ${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 )
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()