[cmake-developers] A goal for a simple Android toolchain file.

Eric Wing ewmailing at gmail.com
Thu Mar 27 23:09:07 EDT 2014


On 3/26/14, Stephen Kelly <steveire at gmail.com> wrote:
> Eric Wing wrote:
>> I have been using my fork of the Android-CMake (originally from
>> OpenCV) that you want to obsolete. My fork contains a lot of fixes to
>> deal with more recent NDK updates and more complicated requirements
>> that I have.
>> https://bitbucket.org/ewing/android-cmake
>
> It's great to have someone here who is both familiar with cmake and with
> Android!
>
>>
>> It is completely reliant on the Android "standalone toolchain"
>> technique which I vastly dislike,
>
> Sorry, I don't know what you're referring to. What is a standalone
> toolchain? This:
>
> https://www.assembla.com/code/android-gb-for-sharp-is01/git/nodes/debug/ndk/docs/STANDALONE-TOOLCHAIN.html
>
> ?
>
> It looks like the primary usefulness of that is to avoid the caller having
> to specify the -sysroot. Do I misunderstand? With CMAKE_SYSROOT in CMake
> 3.0, and with the platform file I proposed, I don't see what makes that
> "standalone toolchain" stuff useful.
>
> Can you explain?
>

Yes, I think that one. In the docs/ directory of the Android NDK you
download, you can find the file: STANDALONE-TOOLCHAIN.html

As I understand it, it basically copies selected things out of the
Android NDK into another directory with a layout more consistent with
typical distributions so you can more easily use 3rd party tools like
CMake. Since Android overloads things like the architectures, the
compiler, and the standard libraries, each permutation you care about
must be copied out into a separate standalone toolchain instance. This
is one of the things that is annoying about it; depending on Android
NDK version, you may have 4 different compilers, each with 4 different
C++ standard libraries (all of which are not necessarily compatible
with each other). That means 4x4=16 permutations. If you want to
distinguish between dynamic and static linking, then you may need to
multiply by 2.

Additionally, each architecture is a permutation, so you need to
multiply another 2 or 3. Then if you can about specific ARM features
not available on all chips (e.g. NEON), you add a bunch more for that.
(The current Android-CMake toolchain seems to have some settings for
those which I've mostly ignored so far.)

Oh yeah, I think each API version needs its own standalone toolchain.

It also looks like the latest Android NDK (r9d) made some additions/changes.
https://developer.android.com/tools/sdk/ndk/index.html


I think it is theoretically possible to invoke the Android build
process without using the standalone toolchain, but the file/directory
layout doesn't necessarily follow normal conventions. I think the
original Android-CMake toolchain did support this, but somewhere
around the 64-bit toolchain release, things broke pretty badly and I
never got it to work. Android is free to re-arrange things and rename
things and they seem to be emboldened to do so in the non-standalone
toolchain.

Additionally, because things are overloaded, you need to be very
careful about not invoking the wrong options on the toolchain. I am
mostly in middleware, so I need to build libraries that other people
use. This means I am extremely sensitive to ABI issues and things like
dynamic linking of C++ standard libraries or specific architecture
optimizations that are not portable are huge no-no's and I need to
trust what the toolchain is doing.

There was also an alternative Android/CMake toolchain somebody wrote
which I think didn't use the standalone toolchain and I tried to work
with, but I started hitting a lot of the above problems which is what
led me back to the more complicated OpenCV one.


>> So while I'm not opposed to a brand new Android toolchain file, I want
>> to assert that it needs to be correct and it does need to handle a
>> variety of cases. So learn as much as you can from the existing ones.
>
> My aim is to put the things which should be in a Android.cmake platform file
>
> shipped with CMake into such a file. Some things belong in such a file, I
> think, and others belong in a toolchain file maintained externally.
>
>> In my fork, I spent a lot of time re-reverse-engineering the
>> standard/default Android flags passed to the compiler. OpenCV took too
>> many liberties with changing what Android passes normally which
>> resulted in unexpected/broken behavior for some of my other projects.
>> I think a very conservative, deferential approach should be taken.
>
> If you can provide details, I think that would be useful.

I wrote some comments in the changelog history in the comments of the
file. My Mercurial history also has some stuff. There are too many
details for me to remember. However, my general conclusion was try to
match watch Android does by default (i.e. same flags). Another example
is, I would defer to using the official "stable" compiler unless
overridden. I think it is still gcc 4.6, not 4.8. I presume there is a
reasoning behind the one they pick as the default/stable.


>> I
>> would also like it to understand multiple architectures which would
>> also go a long way to simplifying the end-user experience, though I'm
>> worried this might take deeper CMake changes.
>
> I expect so, but knowing what the needs are helps inform what those changes
>
> might look like.
>
>  http://public.kitware.com/Bug/view.php?id=14539
>

I'm not sure either. I recall an old thread about this, and it sounded
like CMake doesn't currently have the infrastructure to handle this.
Mac/iOS avoid the problem because Apple overloaded the compiler so it
could build Universal binaries with some additional flags which can
avoid problems like needing to invoke the compiler/linker multiple
times and having different files with different names or
subdirectories.

One other issue I would like to see fixed is that it is impossible to
change some of the settings like architecture after the first
generation. I find that this makes the CMake GUI interface completely
useless to me and I always have to load up all my parameters up front
on the command line.

>>
>>>  set(ANDROID_SDK_ROOT "/home/stephen/android/android-sdk-linux/")
>>>  set(ANDROID_NDK_ROOT "/home/stephen/android/android-ndk-r9/")
>>
>> It should also handle the semi-blessed/official Android environmental
>> variables like ANDROID_SDK_ROOT and ANDROID_NDK_ROOT so you don't have
>> to explicitly set them in CMake scripts.
>
> It does. Did you look at the Android.cmake I posted?

I only skimmed it. I missed the $ENV{ANDROID_SDK_ROOT} you had. I'm
glad you included that. Looks like there are some new ones we should
support like NDK_TOOLCHAIN_VERSION.


>>>  set(ANDROID_NDK_PLATFORM "android-18")
>>
>> It should automatically detect and use the latest Android target API
>> if it is not explicitly specified.
>
> My Android.cmake also reads that from the environment. If there's a way to
> detect it automatically, that might be a good idea. Can you say how?

My idea is just to scan the directories in the NDK itself and take the
highest number found.

In platforms/, there are the following directories:
android-13/
android-14/
android-15/
android-16/
android-17/
android-18/
android-19/
android-3/
android-4/
android-5/
android-8/
android-9/

19 is the max in my NDK, so that should be the one that is picked by default.


> Can you tell me for certain whether you looked at the Android.cmake file I
> linked to already? Knowing whether you did would help our discussion I
> think.
>

I'm looking at it now. I think you understand the non-standalone
toolchain better than me, so you might be able to lead that part of
the discussion.

Though, one other consideration is maintainability. Android keeps
changing version numbers and moving/breaking things. I don't have a
good answer, but you can see in the OpenCV toolchain, there is a lot
of version fixes which are pretty unwieldily. One simple idea is to
not try to write a single toolchain that handles all the differences,
but just copy the file and make changes as needed for each NDK
version.

Thanks,
Eric
-- 
Beginning iPhone Games Development
http://playcontrol.net/iphonegamebook/



More information about the cmake-developers mailing list