# Embedding dylib in a macos bundle

**URL:** https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465
**Category:** Usage
**Tags:** os:macos
**Created:** [July 5, 2023, 4:17pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465 "2023-07-05T16:17:43Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [July 5, 2023, 4:17pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/1 "2023-07-05T16:17:43Z")

</div>

I am building a macos bundle that links using a `dylib` that is included in my project (not built).

```cmake
add_executable(${target} MACOSX_BUNDLE main.cpp)
add_library(google_angle_EGL SHARED IMPORTED)
set_target_properties(google_angle_EGL PROPERTIES
      IMPORTED_LOCATION ${GOOGLE_ANGLE_DIR}/macOS/libEGL.dylib
      FRAMEWORK TRUE
      MACOSX_FRAMEWORK_BUNDLE_VERSION "1.0.0"
      MACOSX_FRAMEWORK_IDENTIFIER "com.google.angle.EGL"
      MACOSX_FRAMEWORK_SHORT_VERSION_STRING "1.0.0"
      )
target_link_libraries(${target} PRIVATE google_angle_EGL)

```

When the bundle gets generated, the imported library is not included in the “.app” although it is declared as a framework (I followed the instructions found in Professional CMake (section 24.3) for how to included a framework).

Any idea why this is not working? Is it because the library is imported instead of compiled? What can I do to embed the library in the .app?

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [July 5, 2023, 10:38pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/2 "2023-07-05T22:38:48Z")

</div>

The part of Professional CMake that you referred to is indeed only for frameworks built as part of your project. The `FRAMEWORK` target property only matters for targets built by your project too (you can’t rely on it being set for imported targets that are frameworks).

I don’t know off-hand whether the `XCODE_EMBED_FRAMEWORKS` target property handles imported targets. You’d probably have to look through the CMake source code to determine whether that is expected to work or not.

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [July 7, 2023, 2:05pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/3 "2023-07-07T14:05:26Z")

</div>

After much searching and banging my head against the wall for days, I am still at a loss. I have looked into `BundleUtilities` and I have made progress, but still having issues.

What I have now is a cmake script to invoke `BundleUtilities` like this:

```cmake
separate_arguments(libs UNIX_COMMAND ${ARG_LIBS})
include(BundleUtilities)
get_bundle_and_executable(${ARG_EXECUTABLE} bundle executable valid)
if(valid)
  set(FRAMEWORK_PATH "${bundle}/Contents/Frameworks")
  foreach (lib IN LISTS libs)
    cmake_path(GET lib FILENAME filename)
    set(bundle_lib "${FRAMEWORK_PATH}/${filename}")
# file(COPY "${lib}" DESTINATION "${FRAMEWORK_PATH}")
    copy_resolved_item_into_bundle("${lib}" "${bundle_lib}")
    list(APPEND bundle_libs "${bundle_lib}")
  endforeach ()
  fixup_bundle(${bundle} "${bundle_libs}" "")
endif()

```

The script gets invoked like this:

```cmake
  add_custom_target(post_process
      COMMAND ${CMAKE_COMMAND} -DARG_EXECUTABLE="$<TARGET_FILE:${target}>" -DARG_LIBS="${google_angle_libs}" -P "${CMAKE_SOURCE_DIR}/cmake/MacOSCopyDynamicLibraries.cmake"
      DEPENDS ${target})

```

This generates the bundle (.app) with the proper format with the 2 libraries under `test_raylib.app/Contents/Framework`

If I comment out the `fixup_bundle` line, the executable (`test_raylib.app/Contents/MacOS/test_raylib`) is like this:

```auto
> otool -L test_raylib
test_raylib:
... truncated
	./libEGL.dylib (compatibility version 0.0.0, current version 0.0.0)
	./libGLESv2.dylib (compatibility version 0.0.0, current version 0.0.0)
... truncated

```

And of course that does not work, because it cannot find the libraries:

```plaintext
Library not loaded: */libEGL.dylib
Referenced from: <7E771F4F-2129-32E9-8EB6-1EABC34E6ECA> /Volumes/VOLUME/*/test_raylib.app/Contents/MacOS/test_raylib
Reason: tried: '*/libEGL.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS*/libEGL.dylib' (no such file), '*/libEGL.dylib' (no such file), '/usr/local/lib/libEGL.dylib' (no such file), '/usr/lib/libEGL.dylib' (no such file, not in dyld cache), '//libEGL.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS//libEGL.dylib' (no such file), '//libEGL.dylib' (no such file), '/usr/local/lib/libEGL.dylib' (no such file), '/usr/lib/libEGL.dylib' (no such file, not in dyld cache)
(terminated at launch; ignore backtrace)

```

If I restore the `fixup_bundle` line, then the executable seems to be properly “fixed” as in, now the path is correct:

```auto
> otool -L test_raylib
test_raylib:
... truncated
	@executable_path/../Frameworks/libEGL.dylib (compatibility version 0.0.0, current version 0.0.0)
	@executable_path/../Frameworks/libGLESv2.dylib (compatibility version 0.0.0, current version 0.0.0)
... truncated

```

But when I run it fails again, this time with a different message:

```plaintext
Exception Type: EXC_BAD_ACCESS (SIGKILL (Code Signature Invalid))

```

Note that I never run any kind of code signature at all.

Any idea what I can do to fix this issue. I didn’t think it was going to be this hard to add an external dylib to my project!

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [July 9, 2023, 4:35pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/4 "2023-07-09T16:35:45Z")

</div>

You might be able to adapt the `.apple` scripts [here](https://gitlab.kitware.com/paraview/common-superbuild/-/tree/920d9bc5c6c69fd945df84668f50aca34cdf5f6f/cmake/scripts) to do what you need. There are some comments around that should help guide as the CMake is probably not 100% useful as-is for arbitrary projects.

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [July 9, 2023, 6:07pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/5 "2023-07-09T18:07:07Z")

</div>

After more trial and error, I was finally able to come up with a satisfactory solution.

First of all, I could never make `BundleUtilities/fixup_bundle` work. I have a feeling that `fixup_bundle` ended up removing some `rpath` in one of the libraries which made it fail to load.

So this is what I came up with. I have no idea whether it is the right approach, but it does work for my use case:

Following [Apple’s documentation](https://developer.apple.com/documentation/xcode/embedding-nonstandard-code-structures-in-a-bundle), I manually updated the 2 libraries that I am using, something like this:

```plaintext
> install_name_tool -id "@rpath/libEGL.dylib" libEGL.dylib
> codesign -s "-" -fv libEGL.dylib

```

Then I simply link with the modified libraries:

```cmake
  set(GOOGLE_ANGLE_DIR "${CMAKE_CURRENT_LIST_DIR}/external/google/angle")
  list(APPEND google_angle_libs "${GOOGLE_ANGLE_DIR}/macOS/libEGL.dylib" "${GOOGLE_ANGLE_DIR}/macOS/libGLESv2.dylib")
  target_link_libraries(${target} PRIVATE "${google_angle_libs}")

```

Then I added a target property to make sure that the rpath is correct:

```cmake
set_target_properties(${target} PROPERTIES
    INSTALL_RPATH "@executable_path/../Frameworks"
)

```

And then finally, I copy the libraries during install

```cmake
install(
    FILES "${google_angle_libs}"
    DESTINATION "$<TARGET_BUNDLE_DIR_NAME:${target}>/Contents/Frameworks"
)

```

So what happens, is that during the build, cmake generates an executable with the following rpath:

```plaintext
Load command 26
      cmd LC_RPATH
      cmdsize 88
      path /Volumes/Vault/tmp/misc-projects/test-raylib/external/google/angle/macOS (offset 12)

```

and the libraries are never copied inside the .app (bundle) because they are found in the source tree… So it just works.

During install, due to the property `INSTALL_RPATH` that is set, cmake will do the right thing and remove the hard-coded rpath and replace it with the correct one and because the libraries are copied inside the bundle (under `Contents/Frameworks`) they will be found as well:

```plaintext
Load command 29
      cmd LC_RPATH
      cmdsize 48
      path @executable_path/../Frameworks (offset 12)

```

---

<div class="post-metadata">

### Author: ![ben.boeckel](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.cmake.org/u/ben.boeckel)
#### Post date: [July 10, 2023, 12:02am UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/6 "2023-07-10T00:02:47Z")

</div>

> [@fry](#):
>
> First of all, I could never make `BundleUtilities/fixup_bundle` work. I have a feeling that `fixup_bundle` ended up removing some `rpath` in one of the libraries which made it fail to load.

Yes, that logic only supports one rpath and doesn’t do the inheritance logic. It’s (one of the reasons) why I wrote those scripts.

---

<div class="post-metadata">

### Author: ![fry](https://discourse.cmake.org/user_avatar/discourse.cmake.org/fry/32/613_2.png) [@fry](https://discourse.cmake.org/u/fry)
#### Post date: [July 10, 2023, 12:53pm UTC](https://discourse.cmake.org/t/embedding-dylib-in-a-macos-bundle/8465/7 "2023-07-10T12:53:34Z")

</div>

@ben.boeckel Thank you for sharing your scripts. I wished I I had seen this sooner as it might have saved me the huge amount of time I spent. Given how complicated the logic is, it is very obvious that it is not a trivial problem…
