I’m seeing conflicting information and wondering what the best practice is for handling frameworks with installed packages. Since find_package is setting a hard coded path on some of the macOS system frameworks I’m seeing the path in the installed package from using the install export commands.
I was originally going to suggest that someone skip find_package for system frameworks and use something such as -framework CoreFoundation as a variable instead. However I’m seeing conflicting information on why not to do that after looking to see if there was a bug on this.
I think one should always use IMPORTED targets and re-find them once installed so that things are fully relocatable (basically, you find the package again so that if it moved, it doesn’t need to be tracked explicitly).
I don’t think I’m following. Since find_package on system frameworks such as CoreFoundation is putting hard coded paths in INTERFACE_LINK_LIBRARIES doesn’t that kind of negate any downstream call on find_package since it’s not a target?
No, because your targets will refer to it as Apple::CoreFoundation (or whatever). When that target gets remade, it can re-find the framework and provide a new path.
That sounds like an ideal state and what I was expecting to see, however it’s not what I’m observing. I’m seeing the hard coded paths in INTERFACE_LINK_LIBRARIES instead of a target.
I don’t know if it is related to your core issue, but you’ve used absolute paths in a couple of places that should use relative paths:
The CMAKE_INSTALL_INCLUDEDIR variable should be relative to the install prefix, so you should only be setting it to include, not ${CMAKE_BINARY_DIR}/install/include.
Similar for installing the export file. The install(EXPORT ...) command should use a relative DESTINATION. It should be just lib/cmake/lib${targetName}, not ${CMAKE_INSTALL_PREFIX}/lib/cmake/lib${targetName}.
As for linking AppKit, don’t use find_library() for that. In a multi-architecture world like Xcode on Apple platforms, find_library() isn’t appropriate because it typically will only find a library for one architecture. In this case, AppKit is expected to be provided by the SDK, so it should be linked by name only. There’s a couple of ways of doing that. With CMake 3.24 or later, I’d recommend using the generator expression that specifies to treat its argument as a framework:
target_link_libraries(${targeTName} PUBLIC $<LINK_LIBRARY:FRAMEWORK,AppKit>)
If you need to support older CMake versions, you can list the framework name with the -framework flag as a single quoted argument:
target_link_libraries(${targeTName} PUBLIC "-framework AppKit")