[cmake-developers] Linking Apple frameworks

Eric Wing ewmailing at gmail.com
Sat Aug 5 23:15:49 EDT 2017


On 8/5/17, Craig Scott <craig.scott at crascit.com> wrote:
> I'm exploring the behaviour of target_link_libraries() where the library to
> be linked is an Apple framework. As part of this, I noticed that the
> following does not work:
>
> target_link_libraries(foo PRIVATE -framework AppKit)
>
>
> This fails because the link command ends up with -framework -lAppKit
> instead of -framework AppKit. Maybe that's expected, but then the following
> DOES work:
>
> target_link_libraries(foo PRIVATE "-framework AppKit")
>
>
> Strangely, with the library quoted as above, the embedded space is not
> escaped, leading to the (desirable but surprising) result -framework AppKit
> in
> the linker command line (i.e. the space isn't escaped and the two words are
> not quoted). *Which of these is the correct way (if either) and are both
> behaving as expected?*


I would argue both of the above are incorrect.

For some history, people passing explicit flags (e.g. -l and -L) was
the exact problem we fought in the first place many years ago. Most
people's scripts wouldn't work when porting to Mac because they
weren't using the CMake abstractions to inform CMake was going on, but
instead bypassing them by setting flags explicitly. So when brought to
Mac, things didn't necessarily work because there were a bunch of
explicit flags written in the scripts (including the Find*.cmake
scripts.) (There was actually a similar problem when porting to Visual
Studio too.)

Then when Apple brought (back) Universal binaries for Intel and then
64-bit, the flags needed to handle the build process got more
complicated. People passing their own flags at the wrong place could
cause problems. (A similar problem occurred as Apple pushed the SDK
model.)

Then (when not talking about system supplied frameworks), when iOS
came, they forbidded dynamic linking for the longest time, so
everything had to be as static libraries. So -framework flags would
not work. Obeying the normal CMake abstractions prevents problems here
too since it knows what to do for static libraries vs. frameworks.

And I would argue this is still wrong today because CMake will have a
harder time understanding there is a library involved here because you
didn't declare it with find_library. Particularly with the Xcode
generator, this information is very useful because the information
isn't always explicitly passed down to a command line invocation.
Sometimes it needs to be declarative so for the Xcode recognizes that
a framework is involved and allows Xcode to handle the correct
behavior.

Already there exists a problem in the Xcode generator that it doesn't
completely use all the framework and library built-in mechanisms, and
this is currently causing me problems for apps that need to be
codesigned. Xcode has a copy-frameworks-and-codessign phase which
CMake does not use. I hope this can be fixed, but I suspect it would
never work with the above two approaches you are asking about.

-Eric


More information about the cmake-developers mailing list