# Best way to consum a binary XCFramework (zip)

**URL:** https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721
**Category:** Usage
**Tags:** os:macos
**Created:** [September 18, 2024, 12:21pm UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721 "2024-09-18T12:21:10Z")
**Posts on this page:** 9
**Page:** 1

<div class="post-metadata">

### Author: ![a4z](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/958977/32.png) [@a4z](https://discourse.cmake.org/u/a4z)
#### Post date: [September 18, 2024, 12:21pm UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/1 "2024-09-18T12:21:10Z")

</div>

Hi, I have a download url to a CoolLib.xcframwork.zip,  
the zip contains `CoolLib.xcframwork`, a folder with the xcframewrok content,

what is the CMake way to download and extract and have the path added to the search, so that `find_package(CoolLib)` works?

I started with `FetchContent_Declare` and `FetchContent_MakeAvailable`, because this is what I know to consume external packages,  
but this flattens the folder hierarchy and there is no CoolLib.xcframwork, only its content, and thus, no xcframework.

what is the right tool now to use, `custom commands`, `ExternalProject_Add`, or something different? Can someone point me in the right direction, please.

---

<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: [September 18, 2024, 9:59pm UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/2 "2024-09-18T21:59:39Z")

</div>

> [@a4z](#):
>
> I started with `FetchContent_Declare` and `FetchContent_MakeAvailable`, because this is what I know to consume external packages,  
> but this flattens the folder hierarchy and there is no CoolLib.xcframwork, only its content, and thus, no xcframework.

This should work, but what’s probably happening is that your archive has just the `CoolLib.xcframework` as its contents. When the top level has just one entry and it is a directory, the extraction assumes it can be stripped off (the URL download method assumes typical archive files, which usually repeat the package name as the top level so that when you extract it, it doesn’t pollute your current directory with the top level files).

You could work around that by overriding the `SOURCE_DIR` in the `FetchContent_Declare()` call, making the directory you specify end in `CoolLib.xcframework`. Then you want the _parent_ of that directory added to your search path. Note that you can’t find a `*.xcframework` with `find_package()`, you can only find it with `find_library()`. An XCFramework is not a package, from CMake’s perspective. If you want to treat `CoolLib` as a package, it would need to follow proper package structure and have an associated `CoolLibConfig.cmake` or `coollib-config.cmake` file.

---

<div class="post-metadata">

### Author: ![a4z](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/958977/32.png) [@a4z](https://discourse.cmake.org/u/a4z)
#### Post date: [September 19, 2024, 7:01am UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/3 "2024-09-19T07:01:26Z")

</div>

Thanks for the info.

Usually, I generate the cmake files via `configure_package_config_file`  
And have the dir layout via cmake install

Here I would need to do that by hand, is that covered in the docs  
the dir layout / where to place the xcframework, and the config files  
(the libs themself are generated via cmake, but then we have to do the xcframework building with extra steps, so the usual way does not work)

---

<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: [September 19, 2024, 10:54pm UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/4 "2024-09-19T22:54:23Z")

</div>

There isn’t quite a “one layout to rule them all” standard, but the `find_package()` documentation does specify all the places it searches for the `<pkgName>Config.cmake` or `<pkgname>-config.cmake` files (see the [Config Mode Search Procedure](https://cmake.org/cmake/help/latest/command/find_package.html#config-mode-search-procedure) section). The `install(TARGETS)` documentation defines default install DESTINATION values for different parts of a target. Between those two, that is about as close as I think the docs officially come to defining where things should generally be installed. You can choose a different layout, but then you’re having to do more work and maybe end up fighting the conventions a bit.

CMake’s XCFramework support is still relatively new. There will be gaps, probably including installing and packaging. I recommend you install your `*.xcframework` to the same place you would install a library or framework. I _think_ `find_library()` should find it automatically like any other framework or library then. The same logic applies if you want to put the `*.xcframework` into a package, you just need to add the `<pkgname>-config.cmake` file. Normally, these files will be in different directories, such as `*.xcframework` in the `lib` directory, and `<pkgname>-config.cmake` in `lib/cmake/pkgname`.

---

<div class="post-metadata">

### Author: ![a4z](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/958977/32.png) [@a4z](https://discourse.cmake.org/u/a4z)
#### Post date: [September 20, 2024, 7:07am UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/5 "2024-09-20T07:07:49Z")

</div>

Thanks for the info! The ‘problem’ is that the xcframework creation does not happen via CMake,  
so there is logically no install step.

With CMake you create the frameworks, or just libraries, for the target platforms, one by one.  
And then use xcodebuild to put them together into the multi platform xcframework.

Therefore, the workflow is a bit different from the usual way.  
Also, getting the xcframework. Is is most likely a binary distribution because the idea is for binary distributions, and the easiest way to get that is by using the file functions for downloading and unpacking.

Will continue looking into that, but it would be nice if cmake’s `find_package` would understand a folder with some xcframework folder in it as a package source, because a XCFramewrok is a package by definition 😉  
And this would keep the interface for the user consistent, because atm I would have to say, Mac, you get a XCFramework, use find\_library. Other platforms, for which we also do binary distributions, those can be found with find\_package. But I have to look into this a bit more, this whole topic is not trivial.

---

<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: [September 20, 2024, 11:36pm UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/6 "2024-09-20T23:36:39Z")

</div>

> [@a4z](#):
>
> …because a XCFramewrok is a package by definition

It isn’t a package by CMake’s definition. It doesn’t provide any CMake target information, transitive properties, etc. I would still recommend wrapping it in a proper CMake package rather than distributing it as a raw XCFramework if you want it to be easy for projects to consume.

> [@a4z](#):
>
> …this whole topic is not trivial.

This is frequently true of packaging, especially so if you need to distribute cross-platform, and ludicrously so if the platforms include Apple. 😬

---

<div class="post-metadata">

### Author: ![a4z](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/958977/32.png) [@a4z](https://discourse.cmake.org/u/a4z)
#### Post date: [September 21, 2024, 7:16am UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/7 "2024-09-21T07:16:22Z")

</div>

I started to develop the idea that (something like) XCFrameworks + [CPS files](https://cps-org.github.io/cps/) might be a viable way to proceed with the ecosystem evolution question.

I agree that the Apple platform is sometimes a bit special, but it also solves some things elegantly or pragmatically.

Btw, I am amazed the CMake was able to figure out the include paths for the XCFramework magically. That is something XCode seems to fail with (probably because its all about Swift now).

But I also wonder about the rules CMake follows. Yesterday, I thought, if I have the same module definition and includes for all platforms, why not have just 1 include folder on the top level instead of one for each architecture/platform?

Is there a location I could look up how cmake resolves that?  
I found some logic in cmComputeLinkInformation.cxx, but could not run the code in my head

---

<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: [September 21, 2024, 7:20am UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/8 "2024-09-21T07:20:10Z")

</div>

> [@a4z](#):
>
> why not have just 1 include folder on the top level instead of one for each architecture/platform?

Frameworks are not required to provide the same headers across all platforms. It would be quite likely that some frameworks will want different variants of the same headers, or even different headers that should only be present for a subset of platforms. Each framework within an `.xcframework` needs to be fully self-contained. Think of an `.xcframework` as essentially just a collection of platform-specific frameworks that the build system knows how to find and use the specific one it needs.

---

<div class="post-metadata">

### Author: ![a4z](https://discourse.cmake.org/letter_avatar_proxy/v4/letter/a/958977/32.png) [@a4z](https://discourse.cmake.org/u/a4z)
#### Post date: [September 21, 2024, 7:30am UTC](https://discourse.cmake.org/t/best-way-to-consum-a-binary-xcframework-zip/11721/9 "2024-09-21T07:30:54Z")

</div>

yes, I know, but a xcframework can also be just a collection of libraries, not frameworks  
and `xcodebuild -create-xcframework` does not require me to specify some include directory if I give it a bunch of libs. And the plist file has a headers section, so in theory … (and now writing this, I wounder why XCode does not find that)  
if it would be the same, it would be nice to avoid redundancy, but it’s also not important

anyhow, nice topic, learned a lot, thanks for your support, Craig!
