Best way to consum a binary XCFramework (zip)

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.

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.

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)

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 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.

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 :wink:
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.

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.

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

I started to develop the idea that (something like) XCFrameworks + CPS files 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

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.

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!