TexConv/cmake/helperfunctions.cmake

149 lines
5.0 KiB
CMake

# Host platform detection
set(CMP_HOST_APPLE OFF)
set(CMP_HOST_LINUX OFF)
set(CMP_HOST_WINDOWS OFF)
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Darwin")
set(CMP_HOST_APPLE ON)
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
set(CMP_HOST_LINUX ON)
elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows")
set(CMP_HOST_WINDOWS ON)
else()
message(FATAL_ERROR "Unknown platform")
endif()
# Helper function for setting persistent CMake options
macro(cmp_option OPTION DESCRIPTION DEFAULT REQUIREMENT)
set(requirement ${ARGV})
list(REMOVE_AT requirement 0 1 2)
if (${requirement})
option(${OPTION} ${DESCRIPTION} ${DEFAULT})
elseif ($CACHE{${OPTION}})
message(WARNING "cache = $CACHE{${OPTION}} Turning off ${OPTION} because it requires ${requirement}")
set(${OPTION} OFF)
endif()
if (${${OPTION}})
add_compile_definitions(${OPTION}=1)
message(STATUS "[ON] ${OPTION}")
else()
add_compile_definitions(${OPTION}=0)
message(STATUS "[__] ${OPTION}")
endif()
endmacro()
# Helper function to gather transitive (potential shared/dynamic) dependencies of a target
function(_get_transitive_dylibs _TARGET)
# Clear variable for reuse
if (NOT DEFINED _transitive_search_started)
set(_transitive_search_started ON)
unset(TRANSITIVE_DYLIBS)
endif()
# INTERFACE_LIBRARY targets can only have INTERFACE_LINK_LIBRARIES properties
get_target_property(target_type ${_TARGET} TYPE)
if(target_type STREQUAL "INTERFACE_LIBRARY")
get_target_property(DEPENDENCIES ${_TARGET} INTERFACE_LINK_LIBRARIES)
else()
get_target_property(LINK_LIBRARIES ${_TARGET} LINK_LIBRARIES)
get_target_property(INTERFACE_LINK_LIBRARIES ${_TARGET} INTERFACE_LINK_LIBRARIES)
set(DEPENDENCIES ${LINK_LIBRARIES} ${INTERFACE_LINK_LIBRARIES})
endif()
# Collect transitive dependencies from target
foreach(_DEP ${DEPENDENCIES})
# Check to see if the dependency is a dynamic library
string(REGEX MATCH ".*\\.(so|dll|dylib)(\\.[a-zA-Z0-9\\.]*)?$" dylib ${_DEP})
if (NOT (dylib STREQUAL ""))
list(APPEND TRANSITIVE_DYLIBS ${dylib})
elseif(TARGET ${_DEP})
# # Only traverse targets we have not visited before
get_target_property(dep_type ${_DEP} TYPE)
if(dep_type STREQUAL "INTERFACE_LIBRARY")
# Marks the library for removal but prevents traversing it again
set(DEP_FILE "${_DEP}.interface")
else()
set(DEP_FILE $<TARGET_FILE:${_DEP}>)
endif()
list(FIND TRANSITIVE_DYLIBS ${DEP_FILE} DEP_IN_LIST)
if (DEP_IN_LIST EQUAL -1)
# Add the target to the list
list(APPEND TRANSITIVE_DYLIBS ${DEP_FILE})
# Get the targets dependencies
_get_transitive_dylibs(${_DEP})
endif()
endif()
endforeach()
# Prune and publish list
list(REMOVE_DUPLICATES TRANSITIVE_DYLIBS)
set(TRANSITIVE_DYLIBS ${TRANSITIVE_DYLIBS} PARENT_SCOPE)
endfunction()
# Helper function to gather transitive (potential shared/dynamic) dependencies of a target
function(get_transitive_dylibs _TARGET)
_get_transitive_dylibs(${_TARGET})
# Prune and publish list
list(FILTER TRANSITIVE_DYLIBS EXCLUDE REGEX "\\.interface$")
set(TRANSITIVE_DYLIBS ${TRANSITIVE_DYLIBS} PARENT_SCOPE)
endfunction()
# Helper function used to copy all dynamic libraries to an output directory
function(executable_post_build_dylibs TARGET_NAME OUTPUT_DIR)
# yields TRANSITIVE_DYLIBS
get_transitive_dylibs(${TARGET_NAME})
# Don't add the custom target if no dynamic libraries were found
list(LENGTH TRANSITIVE_DYLIBS _NUM_DYLIBS)
if(_NUM_DYLIBS GREATER 0)
add_custom_command(
TARGET ${TARGET_NAME}
PRE_BUILD
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/PostBuildCopy.cmake "\"${TRANSITIVE_DYLIBS}\""
${OUTPUT_DIR}
)
endif()
endfunction()
macro(cmp_copy_to_output executable source dest)
add_custom_command(TARGET ${executable} PRE_BUILD
# COMMENT "Copying ${source} -> ${dest}"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
${source}
${dest}
)
endmacro()
macro(cmp_execute_process COMMAND WORKING_DIR)
set(CMD_MSG "")
foreach(CMD ${${COMMAND}})
set(CMD_MSG "${CMD_MSG}${CMD} ")
endforeach()
message(STATUS "Executing process: ${CMD_MSG}")
execute_process(
COMMAND ${${COMMAND}}
WORKING_DIRECTORY ${WORKING_DIR}
ERROR_VARIABLE _stderr
OUTPUT_VARIABLE _stdout
RESULT_VARIABLE _exit_code ENCODING UTF-8
)
if(NOT _exit_code EQUAL 0)
message(STATUS ${_stdout})
if(EXISTS ${VULKAN_OUTPUT_DIR})
file(REMOVE_RECURSE ${VULKAN_OUTPUT_DIR})
endif()
message(FATAL_ERROR "Process exited with non 0 exit code: ${_exit_code}\n${_stderr}")
endif()
endmacro()