[cmake-developers] iOS: direction to official support and questions

Eric Wing ewmailing at gmail.com
Wed Aug 16 10:27:45 EDT 2017


I've been using a derivative of the iOS toolchain for many years that
you probably can find easily with a Google search. It has a lot of
shortcomings, but it generally works. And most of the shortcomings I
think are only solvable by properly fixing/modifying the CMake core.


On 8/15/17, Raffi Enficiaud <raffi.enficiaud at mines-paris.org> wrote:
> Le 10.08.17 à 17:04, Brad King a écrit :
>> On 08/08/2017 08:08 AM, Raffi Enficiaud wrote:
>>> I have looked a bit to the Android toolchains, and I have to say I found
>>> those quite complicated as a first reading :)
>>

I personally think the Android toolchain is way more complicated than
the iOS toolchain. Among the reasons are that every NDK release broke
something different as they kept changing the compiler and conventions
(the gcc to clang move was the most recent biggie, but old-timers
might remember the standalone toolchain difficulties.). Then you have
to pick different API levels because the each NDK release ships a
separate API subtarget for all prior versions of Android. Then add all
the multiple architectures (mips, arm, x86, 64-bit) and the
subvariants (armv5, armv7, armv7+NEON, etc), 4 different C++ standard
libraries you have to choose from, and other nuisances like Android on
Windows...makes the whole thing a mess.


>> Ideally CMake would gain iOS platform modules such that one could
>> set CMAKE_SYSTEM_NAME to `iOS`.


>>> where this path is hard coded, and points to the fat static libraries
>>> prefix path of boost. If I remove this path, FindBoost does not find the
>>> boost libraries anymore (of course I am passing BOOST_ROOT). In
>>> addition, I have this:
>>>
>>> set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM ONLY)
>>> set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
>>> set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
>>
>> These last three lines tell the find commands to only look at
>> paths re-rooted under CMAKE_FIND_ROOT_PATH and CMAKE_SYSROOT.
>> If boost is not under one of those then it won't be found.
>>

That sounds right. The general problem is you don't want to
accidentally pick up OSX stuff on your system.

I've generally used a combination of two things. I modified my
toolchain to have special new root paths which I can define and I put
all my iOS stuff there, and/or I use the -C initial cache feature of
CMake to prespecify the locations. (And sometimes my initial caches
use my new root path variables so the initial cache is flexible and
not hard coded.)

>>> set(CMAKE_MACOSX_BUNDLE YES)
>>
>> Is it possible to build any binary of any form on iOS without this?
>
> You're right, I do not think this is possible.

As far as I know, it always must be a bundle.

> As I understand it, this is a problem of try_compile: as signing of application is required for generating a binary for iOS, this one fails very early when CMake discovers the capabilities of the compiler.

I have not encountered this. I don't think it is true, but I rarely
use try_compile.

Building iOS static libraries are not signed. And I don't think
simulator targets require signing either.

Signing is required for running on device.


That said, there are a ton of other problems related to signing which
are completely broken with CMake.

Right now, the biggest pain point for me is the new Automatic Code
signing. Prior to Xcode 8, you could set a CMake Xcode attribute to
explicitly set the key to use. But this now conflicts with the new
Automatic Code signing, and this his cannot be controlled by a CMake
attribute and it breaks everything. And even if that were fixed, Xcode
needs a second property, the Team. While this can be set by an
attribute, the problem is just about every user has a different team
and it is not easy to know. Xcode has a way of finding out what teams
are available so you can pick it in a drop-down list (same with the
keys). But for a CMake user, this is nearly impossible to know
apriori. I think the only way to fix this is to modify CMake to 1) try
to defer to Xcode's built-in behavior & 2) if the user sets this, some
how don't let CMake overwrite/clobber just that setting when the
project regenerates on an update.

Semi-related is the Mac OS X entitlements system which is connected to
code signing and shipping on the Mac App Store. It has a lot of these
same problems and I think it needs to be fixed in the same fashion.
The entitlements are supposed to show up in a dedicated tab in the
project settings, but CMake projects tend to be blank in this area.

And related to that is the iOS device orientation and launch screen
setting which is the same story.

>
> Currently the main issue I am seeing is the multiarch/multisysroot
> target of XCode that is kind of lost when using CMake. By
> multiarch/multisysroot, I mean that Xcode is able to switch from
> iPhoneSimulatorXY to iPhoneXY without changing the project, and within
> the same view.

Yes, that is a huge problem. I've found this to be very fragile.
However for the moment, it kind of works.
        FIND_LIBRARY(APPLE_UIKIT_LIBRARY "UIKit")
I think this was something I did to my toolchain, but I honestly can't
remember the specifics. It might have had something to do with
SYSROOT.  I think the default one out there was setting something too
aggressively. By removing it, it allowed Xcode to do it's normal
things when switching between simulator and device targets (i.e.
switch the SDK paths), and it still worked.

However, I think the real solution is again to fix CMake so libraries
& frameworks use te exact same built-in mechanism Xcode uses. That way
Xcode takes control of everything in this situation because it looks
no different than a hand-crafted Xcode project in this case.

Additionally, bundling (copying resources) and code signing are
another huge problem. Xcode formally recognizes that libraries and
frameworks must be copied into the bundle during the build process.
There is an explicit settings tab for this now. And it also knows that
it must codesign everything after this step. And all this is an atomic
operation as part of the regular build. When you hit the
build/run/profile buttons in Xcode, all this stuff happens in one step
and also includes the launch in that step. CMake has been resistant to
this workflow for years, and it is a huge problem because this how the
entire process is designed to operate and not supporting this breaks
stuff badly. So again, if we can modify CMake to fully utilize the
built-in Xcode features for libraries & frameworks, I think this
problem gets fixed.


Though there is one more nasty problem with the simulator vs. device
switching. For 3rd party (dynamic) frameworks which were just finally
allowed a few years ago, Apple has failed to give developers a good
solution for dealing with pre-built libraries. Unlike a static
library, Apple doesn't strip the dynamic libraries you don't use in
your bundled framework. So if you built a fat framework with both
simulator and device binareis, you get rejected by the App Store. But
if you don't build a fat framework, there is no Apple supported way to
switch between simulator and device targets on the fly.



So in summary, my feeling is that to fix this, these are the top items
that must be addressed:
1) A way to turn off Automatic Code signing or a way to fully embrace
it so it just works
(may need a way to not clobber manual user settings for key selection
on regenerate)
2) Fix manual code signing (similar to above)
3) Make CMake fully embrace native Xocde mechanisms for libraries &
frameworks (which includes the atomic build/bundle/codesign/run)
4a) Make it easier to build fat binaries and then strip out the unused
ones on the final app build
or
4b) We need CMake to recognize a system where when the user switches
between simulator and device targets, it can also switch 3rd-party SDK
directories which contain separate targets.
5) Fix proper integration for entitlements and device settings

* Extra: I haven't dealt with AppleTV and Apple Watch yet. I don't
know what extra things may be needed besides the LLVM IR "BitCode"
option.

-Eric


P.S. I'm reaching a point where the codesiging is becoming a big
enough problem for me that I'm interested in fixing it. And I might be
able to dedicate some time to it. I saw some other people are already
ahead of me on this and have looked at it in more detail. I'm willing
to help out or collaborate.


More information about the cmake-developers mailing list