jestro
jestro

Reputation: 2593

How to get CMake to embed a private framework into a macOS app bundle?

target_link_libraries links private frameworks fine but it doesn't have a way to copy the frameworks into the app bundle's Frameworks directory. It also doesn't have a way to then update the executable's path to the framework.

So essentially I need CMake to:

  1. Link with a private dylib.
  2. Copy that dylib into the app bundle's Frameworks directory.
  3. Update the executable's path to the dylib.

Upvotes: 4

Views: 1659

Answers (1)

jestro
jestro

Reputation: 2593

I decided to write my own rpaths to the final executable. To prevent CMake from writing build rpaths set CMAKE_SKIP_BUILD_RPATH. This needs to be set before add_executable.

set(CMAKE_SKIP_BUILD_RPATH TRUE)

Then I copy all the dylibs I want to embed into the built app bundle's Frameworks directory. In this case I'm copying MoltenVK which is being stored in the project. ${PROJECT_NAME} is the executable name.

set(APP_BUNDLE_CONTENTS_DIR "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.app/Contents")
set(APP_BUNDLE_FRAMEWORKS_DIR "${APP_BUNDLE_CONTENTS_DIR}/Frameworks")

file(GLOB VULKAN_DYLIB_PATHS "${CMAKE_SOURCE_DIR}/external/vulkan/builds/mac/*")
target_link_libraries(${PROJECT_NAME} ${VULKAN_DYLIB_PATHS})
file(COPY ${VULKAN_DYLIB_PATHS} DESTINATION ${APP_BUNDLE_FRAMEWORKS_DIR})

Then I add an rpath to the executable as a post build command.

add_custom_command(TARGET ${PROJECT_NAME} 
    POST_BUILD COMMAND 
    install_name_tool -add_rpath "@executable_path/../Frameworks/"
    "${APP_BUNDLE_CONTENTS_DIR}/MacOS/${PROJECT_NAME}")

This works for building and debugging with CMake. This won't work when generating an Xcode project. Hopefully I'll find a better cleaner way, but this works for now.

Upvotes: 3

Related Questions