blob: d84101f71d2f934d66d75ae3cdc8097c2e934722 [file] [edit]
# Adds source files to a libclc builtin library target with deduplication. If a
# source with the same basename already exists in the target's SOURCES property
# the new file is skipped. This enables target-specific directories to override
# generic implementations when they are included first.
#
# Sources are specified as paths relative to CMAKE_CURRENT_SOURCE_DIR, or
# relative to BASE_DIR if provided.
function(libclc_add_sources target)
cmake_parse_arguments(ARG "" "BASE_DIR" "FILES" ${ARGN})
if(NOT ARG_BASE_DIR)
set(ARG_BASE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
endif()
get_target_property(existing ${target} SOURCES)
set(seen)
foreach(file IN LISTS existing)
get_filename_component(name "${file}" NAME)
list(APPEND seen "${name}")
endforeach()
set(new_sources)
foreach(rel_src IN LISTS ARG_FILES)
get_filename_component(name "${rel_src}" NAME)
if(NOT name IN_LIST seen)
list(APPEND new_sources "${ARG_BASE_DIR}/${rel_src}")
list(APPEND seen "${name}")
endif()
endforeach()
if(new_sources)
target_sources(${target} PRIVATE ${new_sources})
set(inc_dirs)
foreach(file IN LISTS new_sources)
get_filename_component(dir "${file}" DIRECTORY)
list(APPEND inc_dirs "${dir}")
endforeach()
list(REMOVE_DUPLICATES inc_dirs)
target_include_directories(${target} PRIVATE ${inc_dirs})
endif()
endfunction()
# Appends a compile option to the given source files. Source paths are
# relative to CMAKE_CURRENT_SOURCE_DIR. The property is set in the
# top-level libclc directory scope.
function(libclc_set_source_options option)
set(srcs ${ARGN})
list(TRANSFORM srcs PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/")
set_property(SOURCE ${srcs}
DIRECTORY ${LIBCLC_SOURCE_DIR}
APPEND PROPERTY COMPILE_OPTIONS ${option}
)
endfunction()
# Creates an object library target for libclc builtins and configures its
# compile options, include directories, and definitions. Subdirectories
# populate sources via libclc_add_sources() after this call.
function(libclc_add_builtin_library target_name)
cmake_parse_arguments(ARG
""
"FOLDER;SOURCE_SUB_DIR"
"COMPILE_OPTIONS;INCLUDE_DIRS;COMPILE_DEFINITIONS"
${ARGN}
)
if(NOT ARG_SOURCE_SUB_DIR)
message(FATAL_ERROR "SOURCE_SUB_DIR is required for libclc_add_builtin_library")
endif()
add_library(${target_name} OBJECT)
target_compile_options(${target_name} PRIVATE ${ARG_COMPILE_OPTIONS})
target_include_directories(${target_name} PRIVATE ${ARG_INCLUDE_DIRS})
target_compile_definitions(${target_name} PRIVATE ${ARG_COMPILE_DEFINITIONS})
set_target_properties(${target_name} PROPERTIES FOLDER ${ARG_FOLDER})
# Populate sources.
add_subdirectory(
${LIBCLC_SOURCE_DIR}/${ARG_SOURCE_SUB_DIR}
${CMAKE_CURRENT_BINARY_DIR}/${target_name}
)
endfunction()
# Builds a builtin library from sources, links it with any internalized
# dependencies, produces the final output file, and registers it for
# installation.
function(libclc_add_library target_name)
cmake_parse_arguments(ARG
""
"ARCH;TRIPLE;TARGET_TRIPLE;SOURCE_TARGET;SOURCE_SUB_DIR;OUTPUT_FILENAME;PARENT_TARGET"
"COMPILE_OPTIONS;INCLUDE_DIRS;COMPILE_DEFINITIONS;INTERNALIZE_LIBRARIES;OPT_FLAGS"
${ARGN}
)
if(NOT ARG_SOURCE_TARGET)
message(FATAL_ERROR "SOURCE_TARGET is required for libclc_add_library")
endif()
if(NOT ARG_OUTPUT_FILENAME)
message(FATAL_ERROR "OUTPUT_FILENAME is required for libclc_add_library")
endif()
if(NOT ARG_PARENT_TARGET)
message(FATAL_ERROR "PARENT_TARGET is required for libclc_add_library")
endif()
libclc_add_builtin_library(${ARG_SOURCE_TARGET}
COMPILE_OPTIONS ${ARG_COMPILE_OPTIONS}
INCLUDE_DIRS ${ARG_INCLUDE_DIRS}
COMPILE_DEFINITIONS ${ARG_COMPILE_DEFINITIONS}
SOURCE_SUB_DIR ${ARG_SOURCE_SUB_DIR}
FOLDER "libclc/Device IR/Intermediate"
)
set(library_dir ${LIBCLC_OUTPUT_LIBRARY_DIR}/${ARG_TARGET_TRIPLE})
file(MAKE_DIRECTORY ${library_dir})
# Create a combined static archive from all object libraries for installation.
set(archive_target ${target_name}.a)
add_library(${archive_target} STATIC)
target_link_libraries(${archive_target} PRIVATE
${ARG_SOURCE_TARGET} ${ARG_INTERNALIZE_LIBRARIES}
)
set_target_properties(${archive_target} PROPERTIES
OUTPUT_NAME ${ARG_OUTPUT_FILENAME}
PREFIX ""
ARCHIVE_OUTPUT_DIRECTORY ${library_dir}
FOLDER "libclc/Device IR/Library"
)
# Link the object files, using a temporary library for internalization.
set(linked_bc ${CMAKE_CURRENT_BINARY_DIR}/${target_name}.linked.bc)
set(link_cmd ${llvm-link_exe})
set(link_deps ${llvm-link_target})
add_library(${target_name}-src STATIC)
target_link_libraries(${target_name}-src PRIVATE ${ARG_SOURCE_TARGET})
set_target_properties(${target_name}-src PROPERTIES
FOLDER "libclc/Device IR/Library"
)
list(APPEND link_cmd $<TARGET_FILE:${target_name}-src>)
list(APPEND link_deps ${target_name}-src)
if(ARG_INTERNALIZE_LIBRARIES)
list(APPEND link_cmd --internalize --only-needed)
foreach(lib ${ARG_INTERNALIZE_LIBRARIES})
add_library(${target_name}-${lib} STATIC)
target_link_libraries(${target_name}-${lib} PRIVATE ${lib})
set_target_properties(${target_name}-${lib} PROPERTIES
FOLDER "libclc/Device IR/Library"
)
list(APPEND link_cmd $<TARGET_FILE:${target_name}-${lib}>)
list(APPEND link_deps ${target_name}-${lib})
endforeach()
endif()
list(APPEND link_cmd -o ${linked_bc})
add_custom_command(OUTPUT ${linked_bc}
COMMAND ${link_cmd}
DEPENDS ${link_deps}
)
string(REPLACE "-" ";" triple_parts "${ARG_TRIPLE}")
list(GET triple_parts 2 triple_os)
if(ARG_ARCH IN_LIST LIBCLC_ARCHS_SPIRV AND NOT triple_os STREQUAL vulkan)
# 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 ${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 "libclc/Device IR/Library"
)
add_dependencies(${ARG_PARENT_TARGET} ${target_name} ${archive_target})
install(FILES ${builtins_lib} $<TARGET_FILE:${archive_target}>
DESTINATION ${LIBCLC_INSTALL_DIR}/${ARG_TARGET_TRIPLE}
COMPONENT ${ARG_PARENT_TARGET}
)
endfunction()