osxbundle: bundle vulkan driver and layers

only bundle synchronization2 layer for older vulkan/MoltenVK versions
where it is needed.

Fixes #13232
This commit is contained in:
der richter 2024-02-17 19:54:03 +01:00
parent 0e441525cf
commit 6b5b4b74b1
1 changed files with 72 additions and 0 deletions

View File

@ -5,6 +5,8 @@ import os
import sys
import shutil
import subprocess
import json
from distutils.dir_util import copy_tree
from functools import partial
sys_re = re.compile("^/System")
@ -82,6 +84,13 @@ def resolve_lib_path(objfile, lib, rapths):
raise Exception('Could not resolve library: ' + lib)
def check_vulkan_max_version(version):
try:
result = subprocess.check_output("pkg-config vulkan --max-version=" + version, shell = True)
return True
except:
return False
def install_name_tool_change(old, new, objfile):
subprocess.call(["install_name_tool", "-change", old, new, objfile], stderr=subprocess.DEVNULL)
@ -109,6 +118,9 @@ def libraries(objfile, result = dict(), result_relative = set(), rapths = []):
def lib_path(binary):
return os.path.join(os.path.dirname(binary), 'lib')
def resources_path(binary):
return os.path.join(os.path.dirname(binary), '../Resources')
def lib_name(lib):
return os.path.join("@executable_path", "lib", os.path.basename(lib))
@ -157,6 +169,61 @@ def process_swift_libraries(binary):
print(">> setting additional rpath for swift libraries")
install_name_tool_add_rpath("@executable_path/lib", binary)
def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode):
# https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderDriverInterface.md#example-macos-driver-search-path
# https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderLayerInterface.md#macos-layer-discovery
loaderSystemSearchFolders = [
os.path.join(os.path.expanduser("~"), ".config", loaderRelativeFolder),
os.path.join("/etc/xdg", loaderRelativeFolder),
os.path.join("/usr/local/etc", loaderRelativeFolder),
os.path.join("/etc", loaderRelativeFolder),
os.path.join(os.path.expanduser("~"), ".local/share", loaderRelativeFolder),
os.path.join("/usr/local/share", loaderRelativeFolder),
os.path.join("/usr/share/vulkan", loaderRelativeFolder),
]
loaderSystemFolder = ""
for loaderSystemSearchFolder in loaderSystemSearchFolders:
if os.path.exists(loaderSystemSearchFolder):
loaderSystemFolder = loaderSystemSearchFolder
break
if not loaderSystemFolder:
print(">>> could not find loader folder " + loaderRelativeFolder)
return
loaderBundleFolder = os.path.join(resources_path(binary), loaderRelativeFolder)
loaderSystemPath = os.path.join(loaderSystemFolder, loaderName)
loaderBundlePath = os.path.join(loaderBundleFolder, loaderName)
libraryRelativeFolder = "../../../Frameworks/"
if not os.path.exists(loaderSystemPath):
print(">>> could not find loader " + loaderName)
return
if not os.path.exists(loaderBundleFolder):
os.makedirs(loaderBundleFolder)
loaderSystemFile = open(loaderSystemPath, 'r')
loaderJsonData = json.load(loaderSystemFile)
librarySystemPath = os.path.join(loaderSystemFolder, loaderJsonData[libraryNode]["library_path"])
if not os.path.exists(librarySystemPath):
print(">>> could not find loader library " + librarySystemPath)
return
print(">>> modifiying and writing loader json " + loaderName)
loaderBundleFile = open(loaderBundlePath, 'w')
loaderLibraryName = os.path.basename(librarySystemPath)
loaderJsonData[libraryNode]["library_path"] = os.path.join(libraryRelativeFolder, loaderLibraryName)
json.dump(loaderJsonData, loaderBundleFile, indent=4)
print(">>> copying loader library " + loaderLibraryName)
frameworkBundleFolder = os.path.join(loaderBundleFolder, libraryRelativeFolder)
if not os.path.exists(frameworkBundleFolder):
os.makedirs(frameworkBundleFolder)
shutil.copy(librarySystemPath, os.path.join(frameworkBundleFolder, loaderLibraryName))
def remove_dev_tools_rapths(binary):
for path in get_rpaths_dev_tools(binary):
install_name_tool_delete_rpath(path, binary)
@ -177,5 +244,10 @@ def main():
print(">> copying and processing swift libraries")
process_swift_libraries(binary)
print(">> copying and processing vulkan loader")
process_vulkan_loader(binary, "MoltenVK_icd.json", "vulkan/icd.d", "ICD")
if check_vulkan_max_version("1.3.261.1"):
process_vulkan_loader(binary, "VkLayer_khronos_synchronization2.json", "vulkan/explicit_layer.d", "layer")
if __name__ == "__main__":
main()