build2cmake/src/templates/metal/compile-metal.cmake (58 lines of code) (raw):
# Metal shader compilation function
function(compile_metal_shaders TARGET_NAME METAL_SOURCES)
# Find the Metal compiler
find_program(METAL_COMPILER xcrun REQUIRED)
# Set Metal compiler flags
set(METAL_FLAGS "-std=metal3.0" "-O2")
# Output directory for compiled metallib
set(METALLIB_OUTPUT_DIR "${CMAKE_BINARY_DIR}/metallib")
file(MAKE_DIRECTORY ${METALLIB_OUTPUT_DIR})
# Separate .metal files from .h files and compile .metal files to .air
set(AIR_FILES)
set(METAL_FILES)
set(HEADER_FILES)
foreach(SOURCE_FILE ${METAL_SOURCES})
if(SOURCE_FILE MATCHES "\\.metal$")
list(APPEND METAL_FILES ${SOURCE_FILE})
elseif(SOURCE_FILE MATCHES "\\.h$")
list(APPEND HEADER_FILES ${SOURCE_FILE})
endif()
endforeach()
foreach(METAL_FILE ${METAL_FILES})
get_filename_component(METAL_NAME ${METAL_FILE} NAME_WE)
set(AIR_FILE "${CMAKE_BINARY_DIR}/${METAL_NAME}.air")
# Include header files as dependencies
set(ALL_DEPENDENCIES ${CMAKE_CURRENT_SOURCE_DIR}/${METAL_FILE})
foreach(HEADER_FILE ${HEADER_FILES})
list(APPEND ALL_DEPENDENCIES ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER_FILE})
endforeach()
add_custom_command(
OUTPUT ${AIR_FILE}
COMMAND ${METAL_COMPILER} -sdk macosx metal ${METAL_FLAGS}
-c ${CMAKE_CURRENT_SOURCE_DIR}/${METAL_FILE}
-o ${AIR_FILE}
DEPENDS ${ALL_DEPENDENCIES}
COMMENT "Compiling Metal shader ${METAL_FILE} to ${AIR_FILE}"
VERBATIM
)
list(APPEND AIR_FILES ${AIR_FILE})
endforeach()
# Link all .air files into a single .metallib
set(METALLIB_FILE "${METALLIB_OUTPUT_DIR}/${TARGET_NAME}.metallib")
add_custom_command(
OUTPUT ${METALLIB_FILE}
COMMAND ${METAL_COMPILER} -sdk macosx metallib ${AIR_FILES}
-o ${METALLIB_FILE}
DEPENDS ${AIR_FILES}
COMMENT "Linking Metal library ${METALLIB_FILE}"
VERBATIM
)
# Create a custom target for the metallib
add_custom_target(${TARGET_NAME}_metallib ALL DEPENDS ${METALLIB_FILE})
# Add dependency to main target
add_dependencies(${TARGET_NAME} ${TARGET_NAME}_metallib)
# Set property so we can access the metallib path later
set_target_properties(${TARGET_NAME} PROPERTIES
METALLIB_FILE ${METALLIB_FILE}
)
endfunction()