KhronosGroup / MoltenVK

MoltenVK is a Vulkan Portability implementation. It layers a subset of the high-performance, industry-standard Vulkan graphics and compute API over Apple's Metal graphics framework, enabling Vulkan applications to run on macOS, iOS and tvOS.
Apache License 2.0
4.76k stars 419 forks source link

Missing dylib symlink breaks cmake's FindVulkan.cmake for MoltenVK optional component #2191

Closed SRSaunders closed 6 months ago

SRSaunders commented 6 months ago

cmake's FindVulkan.cmake module looks for the MoltenVK optional component at: $ENV{VULKAN_SDK}/../MoltenVK/dylib/... See the following code snippet from FindVulkan.cmake:

...

if(APPLE AND DEFINED ENV{VULKAN_SDK})
  cmake_path(SET _MoltenVK_path NORMALIZE "$ENV{VULKAN_SDK}/../MoltenVK")
  if(EXISTS "${_MoltenVK_path}")
    list(APPEND _Vulkan_hint_include_search_paths
      "${_MoltenVK_path}/include"
    ) 
    if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
      list(APPEND _Vulkan_hint_library_search_paths
        "${_MoltenVK_path}/dylib/iOS"
      )
    elseif(CMAKE_SYSTEM_NAME STREQUAL "tvOS")
      list(APPEND _Vulkan_hint_library_search_paths
        "${_MoltenVK_path}/dylib/tvOS"
      )
    else()
      list(APPEND _Vulkan_hint_library_search_paths
        "${_MoltenVK_path}/dylib/macOS"
      )
    endif()
  endif() 
  unset(_MoltenVK_path)
endif()

...

While this path no longer exists in the standard Vulkan SDK (as of 1.3.275.0), it continued to exist in the MoltenVK project structure. This made it quite useful for app development using a locally-built MoltenVK library where you could just change the VULKAN_SDK path to MoltenVK/Package/Release/MoltenVK and cmake would find the library.

Since MoltenVK 1.2.8, this symlink is now missing in the MoltenVK project directory structure, and cmake can no longer find the MoltenVK component in the project tree using find_package(Vulkan OPTIONAL_COMPONENTS MoltenVK). Note FindVulkan.cmake does have other hint paths for the standard Vulkan SDK, so that part is not broken for finding the MoltenVK optional component by standard SDK users. This issue is mainly for custom builds of MoltenVK.

Would you consider reinstating a symlink at MoltenVK/Package/Release/MoltenVK/dylib ?

billhollings commented 6 months ago

PR #2195 fixes this. Please retest with latest MoltenVK and close this issue if it accomplishes what you need.

Please be aware that iOS and tvOS do not support naked dylib files, so MoltenVK now produces dynamically linking frameworks for all platforms in MoltenVK/dynamic/MoltenVK.xcframework. You might want to request the folks at CMake to modify FindVulkan.cmake to dynamically link to MoltenVK/dynamic/MoltenVK.xcframework if possible.

richard-lunarg commented 6 months ago

If you use the latest Vulkan SDK (1.3.280.1), FindVulkan.cmake finds the frameworks now. First you have to run either:

source ~/VulkanSDK/1.3.281.1/setup-env.sh or source ~/VulkanSDK/1.3.280.1/iOS/setup-env.sh

billhollings commented 6 months ago

If you use the latest Vulkan SDK (1.3.280.1), FindVulkan.cmake finds the frameworks now. First you have to run either:

source ~/VulkanSDK/1.3.281.1/setup-env.sh or source ~/VulkanSDK/1.3.280.1/iOS/setup-env.sh

@richard-lunarg

Thanks for explaining that.

How does Vulkan SDK 1.3.280.1 allow FindVulkan.cmake make use of frameworks instead of dylibs? The FindVulkan.cmake code excerpt above seems to be hardcoded to dylibs.

And setup-env.sh just seems to be setting generic env vars that don't appear to change how FindVulkan.cmake works, or to retrieve a custom FindVulkan.cmake version.

richard-lunarg commented 6 months ago

I should have mentioned that you need cmake 3.29.0 or later. It works with the recently updated Vulkan Samples repo as a test case. I'm not a cmake guru, so I'm not sure if it's the updated VULKAN_SDK or the addition of the iOS folders to the system path. But it finds the frameworks and incorporates them correctly.

richard-lunarg commented 6 months ago

Ah, I'm confusing the issue. We just got this working with iOS, and that's what I'm thinking of. I just looked at findvulkan.cmake from 3.29.0, and I don't think it's finding it because of VULKAN_SDK, I think it's finding it because we've modified $PATH and it's finding it in the path folders. Again... not a cmake. expert, but it finds the frameworks and uses them for iOS. I confess, I don't use cmake unless I'm forced too, so I have not used it with a desktop macOS project.

SRSaunders commented 6 months ago

PR https://github.com/KhronosGroup/MoltenVK/pull/2195 fixes this. Please retest with latest MoltenVK and close this issue if it accomplishes what you need.

Yes, this works fine now. Thanks for adding the symlink back in.

Please be aware that iOS and tvOS do not support naked dylib files, so MoltenVK now produces dynamically linking frameworks for all platforms in MoltenVK/dynamic/MoltenVK.xcframework. You might want to request the folks at CMake to modify FindVulkan.cmake to dynamically link to MoltenVK/dynamic/MoltenVK.xcframework if possible.

Before I ask the cmake folks for any changes, I would like to clarify a few things:

  1. Is the dylib symlink reinstated only for macOS, or for iOS and tvOS as well?, i.e. should ${_MoltenVK_path}/dylib/iOS and ${_MoltenVK_path}/dylib/tvOS be retained or removed from the code snippet above?
  2. Since I do mostly cross-platform stuff I am less familiar with using Apple-only frameworks, but I do notice a few things about MoltenVK's framework. I believe cmake currently recognizes .framework, but not .xcframework. In other words a developer would have to specify MoltenVK/dynamic/MoltenVK.xcframework/macos-arm64_x86_64 (or other target/arch) for the MoltenVK framework to be discovered by cmake's find_library(MoltenVK_Framework NAMES MoltenVK) function. (sorry - .xcframework now works with cmake 3.29, I was using cmake 3.27 which does not work). And MoltenVK's framework does not currently contain header files (i.e. are not self-contained). This does not simplify finding of include paths since they have to be handled separately from the framework, i.e. as they are today. Is this purposeful, or will this change in the future?

I am not quite sure what I should be asking the cmake guys regarding MoltenVK's framework packaging. At a minimum I would need to know how they will be introduced into the Vulkan SDK which I believe has not fully happened yet (e.g. static frameworks are there but not dynamic). FindVulkan.cmake is primarily concerned with finding Vulkan components within standard locations (either Vulkan SDK or system global). The use case I asked to be fixed was a MoltenVK developer and legacy compatibility use case (and thanks again for fixing). Perhaps the new framework stuff is something you and @richard-lunarg need to inform the cmake guys about as you roll out new Vulkan SDK versions. The main issue I anticipate is differentiating between static and dynamic versions and their path locations within the Vulkan SDK, and determining how cmake deals with that.

billhollings commented 6 months ago

Thanks for following up and providing thoughtful feedback.

Is the dylib symlink reinstated only for macOS, or for iOS and tvOS as well?

Only macOS. The symlink is to the dynamic/dylib directory, which now only contains a macOS subdirectory. This is intentional, as .dylib files, are not permitted on iOS or tvOS, per Apple App Store rules.

And MoltenVK's framework does not currently contain header files...Is this purposeful, or will this change in the future?

For the most part, intentional. The headers are really just Vulkan headers, unless a user is digging into the private MoltenVK API. For now, it's assumed that MoltenVK is primarily a runtime driver, and that Vulkan headers would be included in the app separately (ie. it's a Vulkan app). Having said that, we do include Vulkan headers in the MoltenVK distribution for convenience.

I am not quite sure what I should be asking the cmake guys regarding MoltenVK's framework packaging.

Fair enough. I'm not sure either. According to the note above by @richard-lunarg, CMake 3.29 is able to find the frameworks now, so it appears the CMake folks are on top of it.

richard-lunarg commented 6 months ago

Having said that, we do include Vulkan headers in the MoltenVK distribution for convenience.

The MoltenVK headers are still in the SDK, they are just now in /macOS/include along with the Vulkan headers so that all the headers are in the same place.

SRSaunders commented 6 months ago

HI @richard-lunarg. Well, I just came across the very issue I was concerned about above - how to distinguish between MoltenVK's static versus dynamic frameworks when using CMake to find the MoltenVK library.

After upgrading to CMake 3.29, when I use find_package(Vulkan OPTIONAL_COMPONENTS MoltenVK), the returned value for Vulkan_MoltenVK_LIBRARY is .../1.3.280.0/macOS/lib/MoltenVK.xcframework. Previous versions of CMake would not return an .xcframework path, but instead the dylib path. Even then, this would be okay if CMake 3.29 found the dynamic framework, but unfortunately the SDK is currently shipping with the static framework only. By finding the static library when I really want the dynamic one, my build breaks. How do you intend to solve this going forward? i.e. Will you structure the SDK to support both static and dynamic frameworks? And if so, how will you tell CMake to find one versus the other?

In the short term, I can disable searching for frameworks by activating set(CMAKE_FIND_FRAMEWORK <NEVER | LAST>) in my CMakeLists.txt file. The build will then only look for (or prioritize) dylibs, and ignore frameworks (or search last). I intend to use this approach for now until I understand how you will structure the SDK going forward and how CMake's find_package function can be told to look for dynamic frameworks / libs only.