Files
how-to-vulkan/ktx/cmake/mkvk.cmake
T
2026-06-14 19:09:18 +01:00

203 lines
7.2 KiB
CMake

# Copyright 2015-2020 The Khronos Group Inc.
# SPDX-License-Identifier: Apache-2.0
# Code generation scripts that require a Vulkan SDK installation
# TODO: Rewrite scripts to generate the files from the Vulkan
# registry, vk.xml, in the Vulkan-Docs repo.
# NOTE: Since this must be explicitly included by setting an option,
# require sought packages. However, in order to give an informative
# error, REQUIRED is not used in the find_* commands.
#
# CAUTION: Outputs of custom commands are deleted during a clean
# operation so these targets result in clean deleting what are normally
# considered source files. There appears to be no easy way to avoid
# this. Since only project developers need to use these targets, and
# only occasionally, this misfeature can be tolerated.
if (NOT IOS AND NOT ANDROID)
# Not needed as local custom vulkan_core.h is used. Keeping
# in case we go back to the standard one.
# # find_package doesn't find the Vulkan SDK when building for IOS.
# # I haven't investigated why.
# find_package(Vulkan REQUIRED)
# This cmake file is included from its parent so has the same scope as
# the including file. If we change Vulkan_INCLUDE_DIR, other parts will
# be affected.
set(mkvk_vulkan_include_dir external/dfdutils)
else()
# Skip mkvk. There is no need to use iOS or Android to regenerate
# the files.
return()
endif()
set(vulkan_header "${mkvk_vulkan_include_dir}/vulkan/vulkan_core.h")
# CAUTION: On Windows use a version of Perl built for Windows, i.e. not
# one found in Cygwin or MSYS (Git for Windows). This is needed so the
# generated files have the correct the correct CRLF line endings. The ones
# mentioned write LF line endings (possibly related to some Cygwin or MSYS
# installation setting for handling of text files). The Perl scripts,
# unlike the Awk scripts, have not been modified to always write CRLF
# on Windows.
#
# Strawberry Perl via Chocolatey is recommended.
# choco install strawberryperl
#if(CMAKE_HOST_WIN32 AND NOT CYGWIN_INSTALL_PATH)
# # Git for Windows comes with Perl
# # Trick FindPerl into considering default Git location
# set(CYGWIN_INSTALL_PATH "C:\\Program Files\\Git\\usr")
#endif()
string(APPEND not_found_error
"not found. "
"This is only needed by project maintainers when regenerating source files. "
"To silence, set KTX_GENERATE_VK_FILES OFF.")
find_package(Perl QUIET)
# Painful. Oh for a way to provide custom error messages for failures.
if(NOT PERL_EXECUTABLE)
message(FATAL_ERROR "Perl executable ${not_found_error}")
endif()
set(Ruby_FIND_VIRTUALENV FIRST)
find_package(Ruby 3 QUIET)
if(NOT Ruby_EXECUTABLE)
message(FATAL_ERROR "Ruby v3 executable ${not_found_error}")
endif()
find_path(KTX_SPECIFICATION
NAMES formats.json
PATHS ${PROJECT_SOURCE_DIR}/../KTX-Specification
NO_DEFAULT_PATH)
if(NOT KTX_SPECIFICATION)
message(FATAL_ERROR "KTX-Specification repo clone ${not_found_error}")
endif()
list(APPEND mkvkformatfiles_input
${vulkan_header}
scripts/mkvkformatfiles)
list(APPEND mkvkformatfiles_output
"${PROJECT_SOURCE_DIR}/interface/java_binding/src/main/java/org/khronos/ktx/VkFormat.java"
"${PROJECT_SOURCE_DIR}/interface/js_binding/vk_format.inl"
"${PROJECT_SOURCE_DIR}/interface/python_binding/pyktx/vk_format.py"
"${PROJECT_SOURCE_DIR}/lib/vkformat_enum.h"
"${PROJECT_SOURCE_DIR}/lib/vkformat_typesize.c"
"${PROJECT_SOURCE_DIR}/lib/vkformat_check.c"
"${PROJECT_SOURCE_DIR}/lib/vkformat_str.c"
"${PROJECT_SOURCE_DIR}tests/unittests/vkformat_list.inl")
# CAUTION: When a COMMAND contains VAR="Value" CMake messes up the escaping
# for Bash. With or without VERBATIM, if Value has no spaces CMake changes it
# to VAR=\"Value\". If it has spaces CMake changes it to "VAR=\"Value\"".
# The first causes the quotes to leak into the command that is reading VAR
# breaking, e.g. opening a file that has VAR's value as part of its name.
# The second causes Bash to look for the command 'VAR="Value"' causing it
# to exit with error.
#
# The only workaround I've found is to put the command in a string and invoke
# it with bash -c. This is what we'd have to do on Windows anyway as COMMAND
# defaults to cmd or powershell (not sure which). In this case CMake passes
# to bash a string of the form '"VAR=\"Value\" command arg ..."' which bash
# parses successfully.
list(APPEND mvffc_as_list
scripts/mkvkformatfiles ./ ${vulkan_header})
list(JOIN mvffc_as_list " " mvffc_as_string)
set(mkvkformatfiles_command "${BASH_EXECUTABLE}" -c "${mvffc_as_string}")
add_custom_command(OUTPUT ${mkvkformatfiles_output}
COMMAND ${mkvkformatfiles_command}
DEPENDS ${mkvkformatfiles_input}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Generating VkFormat-related source files"
VERBATIM
)
add_custom_target(mkvkformatfiles
DEPENDS ${mkvkformatfiles_output}
SOURCES ${mkvkformatfiles_input}
)
list(APPEND makevk2dfd_input
${vulkan_header}
external/dfdutils/makevk2dfd.pl)
set(makevk2dfd_output
"${PROJECT_SOURCE_DIR}/external/dfdutils/vk2dfd.inl")
add_custom_command(
OUTPUT ${makevk2dfd_output}
COMMAND "${PERL_EXECUTABLE}" external/dfdutils/makevk2dfd.pl ${vulkan_header} external/dfdutils/vk2dfd.inl
DEPENDS ${makevk2dfd_input}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Generating VkFormat/DFD switch body"
VERBATIM
)
add_custom_target(makevk2dfd
DEPENDS ${makevk2dfd_output}
SOURCES ${makevk2dfd_input}
)
list(APPEND makedfd2vk_input
${vulkan_header}
external/dfdutils/makedfd2vk.pl)
list(APPEND makedfd2vk_output
"${PROJECT_SOURCE_DIR}/external/dfdutils/dfd2vk.inl")
add_custom_command(
OUTPUT ${makedfd2vk_output}
COMMAND ${CMAKE_COMMAND} -E make_directory external/dfdutils
COMMAND "${PERL_EXECUTABLE}" external/dfdutils/makedfd2vk.pl ${vulkan_header} external/dfdutils/dfd2vk.inl
DEPENDS ${makedfd2vk_input}
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
COMMENT "Generating DFD/VkFormat switch body"
VERBATIM
)
add_custom_target(makedfd2vk
DEPENDS ${makedfd2vk_output}
SOURCES ${makedfd2vk_input}
)
list(APPEND makevk2gl_input
${KTX_SPECIFICATION}/generate_format_switches.rb
${KTX_SPECIFICATION}/formats.json)
list(APPEND makevk2gl_output
"${PROJECT_SOURCE_DIR}/lib/vkFormat2glFormat.inl"
"${PROJECT_SOURCE_DIR}/lib/vkFormat2glInternalFormat.inl"
"${PROJECT_SOURCE_DIR}/lib/vkFormat2glType.inl")
# Until we have D3D or Metal loaders these outputs of
# generate_format_switches.rb are unneeded.
list(APPEND makevk2gl_extraneous_files
"${PROJECT_SOURCE_DIR}/lib/vkFormat2dxgiFormat.inl"
"${PROJECT_SOURCE_DIR}/lib/vkFormat2mtlFormat.inl"
)
add_custom_command(
OUTPUT ${makevk2gl_output}
COMMAND "${RUBY_EXECUTABLE}" ${KTX_SPECIFICATION}/generate_format_switches.rb ${PROJECT_SOURCE_DIR}/lib
COMMAND ${CMAKE_COMMAND} -E rm -f ${makevk2gl_extraneous_files}
DEPENDS ${makevk2gl_input}
WORKING_DIRECTORY ${KTX_SPECIFICATION}
COMMENT "Generating VkFormat to OpenGL internal format, format and type switches"
VERBATIM
)
add_custom_target(makevk2gl
DEPENDS ${makevk2gl_output}
SOURCES ${makedvk2gl_input}
)
add_custom_target(mkvk SOURCES ${CMAKE_CURRENT_LIST_FILE})
add_dependencies(mkvk
mkvkformatfiles
makevk2dfd
makedfd2vk
makevk2gl
)