blob: 4c8bf87c5bbf802fb7df17c40ea05c3cf8ba8bae [file] [log] [blame] [edit]
# Converts a list of relative source paths to absolute paths and exports
# it to the parent scope.
macro(libclc_configure_source_list variable path)
set(${variable} ${ARGN})
list(TRANSFORM ${variable} PREPEND "${path}/")
set(${variable} ${${variable}} PARENT_SCOPE)
endmacro()
# Appends a compile option to the given source files. Paths are relative
# to `path` and the property is set in the top-level libclc directory scope.
macro(libclc_configure_source_options path option)
set(_option_srcs ${ARGN})
list(TRANSFORM _option_srcs PREPEND "${path}/")
set_property(SOURCE ${_option_srcs}
DIRECTORY ${LIBCLC_SOURCE_DIR}
APPEND PROPERTY COMPILE_OPTIONS ${option}
)
endmacro()
# Merges OpenCL C source file lists with priority deduplication.
#
# All arguments after the output variable name are treated as source file
# paths. When multiple files share the same basename, the last occurrence
# wins. This allows target-specific files to automatically override generic
# ones.
function(libclc_merge_sources output)
set(all_sources ${ARGN})
set(result)
set(seen_names)
list(REVERSE all_sources)
foreach(f ${all_sources})
get_filename_component(name "${f}" NAME)
if(NOT name IN_LIST seen_names)
list(APPEND seen_names "${name}")
list(PREPEND result "${f}")
endif()
endforeach()
set(${output} ${result} PARENT_SCOPE)
endfunction()
# Creates a static library target for libclc builtins. Derives include
# directories to locate `.inc` files in the same directory.
function(add_libclc_builtin_library target_name)
cmake_parse_arguments(ARG
""
"FOLDER"
"SOURCES;COMPILE_OPTIONS;INCLUDE_DIRS;COMPILE_DEFINITIONS"
${ARGN}
)
set(_inc_dirs)
foreach(f ${ARG_SOURCES})
get_filename_component(dir ${f} DIRECTORY)
list(APPEND _inc_dirs ${dir})
endforeach()
list(REMOVE_DUPLICATES _inc_dirs)
add_library(${target_name} STATIC ${ARG_SOURCES})
target_compile_options(${target_name} PRIVATE ${ARG_COMPILE_OPTIONS})
target_include_directories(${target_name} PRIVATE
${ARG_INCLUDE_DIRS} ${_inc_dirs}
)
target_compile_definitions(${target_name} PRIVATE ${ARG_COMPILE_DEFINITIONS})
set_target_properties(${target_name} PROPERTIES
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
FOLDER ${ARG_FOLDER}
)
endfunction()
# Links one or more libclc builtin libraries together, optionally
# internalizing dependencies, then produces a final .bc or .spv file.
function(link_libclc_builtin_library target_name)
cmake_parse_arguments(ARG
""
"ARCH;TRIPLE;FOLDER;OUTPUT_FILENAME"
"LIBRARIES;INTERNALIZE_LIBRARIES;OPT_FLAGS"
${ARGN}
)
if(NOT ARG_OUTPUT_FILENAME)
message(FATAL_ERROR "OUTPUT_FILENAME is required for link_libclc_builtin_library")
endif()
if(NOT ARG_LIBRARIES)
message(FATAL_ERROR "LIBRARIES is required for link_libclc_builtin_library")
endif()
set(library_dir ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TRIPLE})
file(MAKE_DIRECTORY ${library_dir})
set(linked_bc ${CMAKE_CURRENT_BINARY_DIR}/${target_name}.linked.bc)
set(link_cmd ${llvm-link_exe})
foreach(lib ${ARG_LIBRARIES})
list(APPEND link_cmd $<TARGET_FILE:${lib}>)
endforeach()
if(ARG_INTERNALIZE_LIBRARIES)
list(APPEND link_cmd --internalize --only-needed)
foreach(lib ${ARG_INTERNALIZE_LIBRARIES})
list(APPEND link_cmd $<TARGET_FILE:${lib}>)
endforeach()
endif()
list(APPEND link_cmd -o ${linked_bc})
set(link_deps ${llvm-link_target}
${ARG_LIBRARIES} ${ARG_INTERNALIZE_LIBRARIES}
)
add_custom_command(OUTPUT ${linked_bc}
COMMAND ${link_cmd}
DEPENDS ${link_deps}
)
if(ARG_ARCH STREQUAL spirv OR ARG_ARCH STREQUAL spirv64)
# SPIR-V targets produce a .spv file from the linked bitcode.
set(builtins_lib ${library_dir}/${ARG_OUTPUT_FILENAME}.spv)
if(LIBCLC_USE_SPIRV_BACKEND)
add_custom_command(OUTPUT ${builtins_lib}
COMMAND ${CMAKE_CLC_COMPILER} -c --target=${ARG_TRIPLE}
-mllvm --spirv-ext=+SPV_KHR_fma
-x ir -o ${builtins_lib} ${linked_bc}
DEPENDS ${linked_bc}
)
else()
add_custom_command(OUTPUT ${builtins_lib}
COMMAND ${llvm-spirv_exe}
--spirv-max-version=1.1
--spirv-ext=+SPV_KHR_fma
-o ${builtins_lib} ${linked_bc}
DEPENDS ${llvm-spirv_target} ${linked_bc}
)
endif()
else()
# All other targets produce an optimized .bc file.
set(builtins_lib ${library_dir}/${ARG_OUTPUT_FILENAME}.bc)
add_custom_command(OUTPUT ${builtins_lib}
COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${builtins_lib} ${linked_bc}
DEPENDS ${opt_target} ${linked_bc}
)
endif()
add_custom_target(${target_name} ALL DEPENDS ${builtins_lib})
set_target_properties(${target_name} PROPERTIES
TARGET_FILE ${builtins_lib}
FOLDER ${ARG_FOLDER}
)
endfunction()
# Builds a builtins library from sources, links it with any internalized
# dependencies via link_libclc_builtin_library, and adds a verification test
# for unresolved symbols.
function(add_libclc_library target_name)
cmake_parse_arguments(ARG
""
"ARCH;TRIPLE;TARGET_TRIPLE;OUTPUT_FILENAME;PARENT_TARGET"
"SOURCES;COMPILE_OPTIONS;INCLUDE_DIRS;COMPILE_DEFINITIONS;INTERNALIZE_LIBRARIES;OPT_FLAGS"
${ARGN}
)
if(NOT ARG_OUTPUT_FILENAME)
message(FATAL_ERROR "OUTPUT_FILENAME is required for add_libclc_library")
endif()
if(NOT ARG_PARENT_TARGET)
message(FATAL_ERROR "PARENT_TARGET is required for add_libclc_library")
endif()
if(NOT ARG_SOURCES)
message(FATAL_ERROR "SOURCES is required for add_libclc_library")
endif()
set(builtins_target ${target_name}_clc_builtins)
add_libclc_builtin_library(${builtins_target}
SOURCES ${ARG_SOURCES}
COMPILE_OPTIONS ${ARG_COMPILE_OPTIONS}
INCLUDE_DIRS ${ARG_INCLUDE_DIRS}
COMPILE_DEFINITIONS ${ARG_COMPILE_DEFINITIONS}
FOLDER "libclc/Device IR/Intermediate"
)
link_libclc_builtin_library(${target_name}
ARCH ${ARG_ARCH}
TRIPLE ${ARG_TRIPLE}
LIBRARIES ${builtins_target}
INTERNALIZE_LIBRARIES ${ARG_INTERNALIZE_LIBRARIES}
OPT_FLAGS ${ARG_OPT_FLAGS}
OUTPUT_FILENAME "${ARG_OUTPUT_FILENAME}"
FOLDER "libclc/Device IR/Library"
)
add_dependencies(${ARG_PARENT_TARGET} ${target_name})
set(builtins_file $<TARGET_PROPERTY:${target_name},TARGET_FILE>)
install(FILES ${builtins_file}
DESTINATION ${LIBCLC_INSTALL_DIR}/${ARG_TRIPLE}
COMPONENT ${ARG_PARENT_TARGET}
)
endfunction()