[CMake] CMake + Gradle for Android

Jom O'Fisher jomofisher at gmail.com
Mon Aug 21 18:34:32 EDT 2017


+ a colleague

On Mon, Aug 21, 2017 at 3:11 PM, Jom O'Fisher <jomofisher at gmail.com> wrote:

> You can find that number like this:
> - x = number of externalNativeBuild.cmake.path in your build.gradle files
> - y = number of gradle configurations (like debug and release)
> - z = number of ABIs that you build
>
> The result is x * y * z. To be more accurate, you should consider y and z
> to be functions of each build.gradle file since these can vary.
>
> There is a second set of folders that hold the stripped versions of the
> .so files that is purely managed by the android gradle plugin, so you might
> consider the answer to be 2 * x * y * z.
>
> Hope this helps.
>
>
>
>
>
>
> On Mon, Aug 21, 2017 at 2:41 PM, Robert Dailey <rcdailey.lists at gmail.com>
> wrote:
>
>> This definitely a bit better, but still requires the boilerplate in
>> each leaf gradle file. But I can't seriously complain too much. I
>> think I'm more concerned with the implications this has underneath.
>> First, let me ask just to make sure I'm not misunderstanding: Does
>> each `externalNativeBuild` entry essentially mean 1 CMAKE_BINARY_DIR?
>> How many binary dirs do you manage internally and what determines when
>> they get created?
>>
>> On Mon, Aug 21, 2017 at 2:35 PM, Jom O'Fisher <jomofisher at gmail.com>
>> wrote:
>> > Would it work for your scenario to provide properties in the root
>> > build.gradle:
>> >
>> > ext {
>> >     cmakePath = file "CMakeLists.txt"
>> > }
>> >
>> > And then consume them in the leaf app/build.gradle like this?
>> >
>> > externalNativeBuild {
>> >     cmake {
>> >         path cmakePath
>> >     }
>> > }
>> >
>> > It doesn't fully hide the details but it does centralize the
>> information.
>> >
>> >
>> > On Mon, Aug 21, 2017 at 11:20 AM, Robert Dailey <
>> rcdailey.lists at gmail.com>
>> > wrote:
>> >>
>> >> I wouldn't want to do that, it's too convoluted. I have other
>> >> platforms that use these CMake scripts as well. For example, I run on
>> >> Windows and Linux platforms as well to build the native code. Normal
>> >> CMake behavior is designed to work at a root then go downwards to find
>> >> targets. However it seems Gradle wants to start at a subdirectory and
>> >> work its way up to the root, which is opposite of CMake's intended
>> >> behavior IMHO. Not only that but I want to avoid special-casing
>> >> behavior in CMake just for Android's use.
>> >>
>> >> At the moment it feels like (again referring back to my previous
>> >> example structure) that both App2 and App3 each run CMake in
>> >> independent binary directories instead of sharing 1 binary directory
>> >> and building 2 targets inside of it. I prefer this behavior instead,
>> >> especially since it allows CMake to operate as it was intended. I
>> >> think it's a common case that projects will define multiple targets
>> >> starting from a single root, and expect multiple APKs or java
>> >> dependencies to be built within it.
>> >>
>> >> If I'm misunderstanding or making false assumptions please let me know.
>> >>
>> >>
>> >>
>> >> On Mon, Aug 21, 2017 at 12:00 PM, Jom O'Fisher <jomofisher at gmail.com>
>> >> wrote:
>> >> > Would it work for your situation for the leaf CMakeLists.txt to
>> include
>> >> > the
>> >> > root CMakeLists.txt? Then have the leaf-specific logic in the leaf
>> >> > CMakeLists.txt?
>> >> >
>> >> >
>> >> >
>> >> > On Mon, Aug 21, 2017 at 9:33 AM, Robert Dailey
>> >> > <rcdailey.lists at gmail.com>
>> >> > wrote:
>> >> >>
>> >> >> Basically, yes. We have this sort of structure:
>> >> >>
>> >> >> <Root of git clone>/
>> >> >>     Applications/
>> >> >>         App1/
>> >> >>             build.gradle
>> >> >>             CMakeLists.txt
>> >> >>         App2/
>> >> >>             build.gradle
>> >> >>             CMakeLists.txt
>> >> >>         App3/
>> >> >>             build.gradle
>> >> >>             CMakeLists.txt
>> >> >>     CommonLib/
>> >> >>         build.gradle
>> >> >>         CMakeLists.txt
>> >> >>     CMakeLists.txt
>> >> >>
>> >> >> The libs are defined as follows:
>> >> >>
>> >> >> * CommonLib is a static library (java code builds into a library)
>> >> >>     * No dependencies of its own
>> >> >> * App1 is a shared library (java code builds into a library)
>> >> >>     * Dependencies (both java & native): CommonLib
>> >> >> * App2 is a shared library (java code builds into an APK)
>> >> >>    * Dependencies (both java & native): App1, CommonLib
>> >> >> * App3 is a shared library (java code builds into an APK)
>> >> >>    * Dependencies (both java & native): CommonLib
>> >> >>
>> >> >> In all cases, CMake must be invoked starting at the root
>> >> >> CMakeLists.txt 1 time. Each target can be built from the same binary
>> >> >> directory after that. Previously with ANT, I was building all native
>> >> >> targets first, then moved libs to appropriate directories so that
>> the
>> >> >> 'ant' command would package the libs.
>> >> >>
>> >> >> For gradle, I wanted to avoid redundantly specifying the root
>> >> >> directory in each leaf-level project directory. Using the example
>> >> >> above, the leaf-level directories in this case would be App1, App2,
>> >> >> App3, and CommonLib. However I think we only specify the native
>> CMake
>> >> >> stuff for the java targets that actually output an APK (that would
>> be
>> >> >> App2 and App3 only).
>> >> >>
>> >> >> The ultimate goal is to specify stuff that doesn't change per
>> >> >> independent "module" of ours at the top level so it is transitive /
>> >> >> inherited. Then only specify the differences (e.g. the native CMake
>> >> >> target to build) in the leaf build gradle files. However you
>> indicated
>> >> >> this isn't possible.
>> >> >>
>> >> >>
>> >> >>
>> >> >> On Mon, Aug 21, 2017 at 11:11 AM, Jom O'Fisher <
>> jomofisher at gmail.com>
>> >> >> wrote:
>> >> >> > What you're doing already sounds correct. You can't directly
>> specify
>> >> >> > CMakeLists.txt from the top-level build.gradle. Recommendation is
>> >> >> > that
>> >> >> > it
>> >> >> > should be specified from the build.gradle of the module of the
>> APK.
>> >> >> > Is
>> >> >> > the
>> >> >> > issue that you have multiple APK modules that all reference the
>> same
>> >> >> > CMake
>> >> >> > libraries?
>> >> >> >
>> >> >> > On Mon, Aug 21, 2017 at 9:00 AM, Robert Dailey
>> >> >> > <rcdailey.lists at gmail.com>
>> >> >> > wrote:
>> >> >> >>
>> >> >> >> Thanks this is very helpful. The other question I have is: Is
>> there
>> >> >> >> a
>> >> >> >> place to centrally specify the root CMakeLists.txt? Basically, I
>> >> >> >> want
>> >> >> >> to specify the CMake root in 1 place, and have targets (defined
>> >> >> >> further down in subdirectories) that require APK packaging to
>> >> >> >> specify
>> >> >> >> only the native target name that should be built & packaged.
>> >> >> >>
>> >> >> >> At the moment we specify the root CMakeLists.txt by walking up
>> the
>> >> >> >> tree, paths like "../../../../CMakeLists.txt". I think this
>> should
>> >> >> >> be
>> >> >> >> put at the top-level build gradle file if possible. Is this
>> doable
>> >> >> >> at
>> >> >> >> the moment? What is the recommended setup?
>> >> >> >>
>> >> >> >> On Mon, Aug 21, 2017 at 9:37 AM, Jom O'Fisher <
>> jomofisher at gmail.com>
>> >> >> >> wrote:
>> >> >> >> > Gradle does introspection on the CMake build to find .so
>> targets
>> >> >> >> > and
>> >> >> >> > those
>> >> >> >> > get packaged.
>> >> >> >> > There is also a special case for stl/runtime .so files from the
>> >> >> >> > NDK.
>> >> >> >> > Any additional .so files need to specified in build.gradle
>> using
>> >> >> >> > jniDirs
>> >> >> >> >
>> >> >> >> > On Mon, Aug 21, 2017 at 7:30 AM, Robert Dailey
>> >> >> >> > <rcdailey.lists at gmail.com>
>> >> >> >> > wrote:
>> >> >> >> >>
>> >> >> >> >> How exactly does Gradle package *.so files in an APK? I know
>> that
>> >> >> >> >> ANT
>> >> >> >> >> used to do this for any libs under "libs/<ABI>". Does Gradle
>> do
>> >> >> >> >> some
>> >> >> >> >> introspection into CMake targets to see if outputs are *.so,
>> and
>> >> >> >> >> copy
>> >> >> >> >> those to some location if needed? What about libraries like
>> >> >> >> >> libgnustl_shared.so that come with the NDK? I'd like to know
>> if
>> >> >> >> >> any
>> >> >> >> >> manual copy steps are needed in CMake to put outputs in proper
>> >> >> >> >> locations for the APK build step. I had to do this when using
>> >> >> >> >> ANT.
>> >> >> >> >>
>> >> >> >> >> On Mon, Aug 7, 2017 at 6:16 PM, Jom O'Fisher
>> >> >> >> >> <jomofisher at gmail.com>
>> >> >> >> >> wrote:
>> >> >> >> >> > 1) There is a folder created for each ABI under the project
>> >> >> >> >> > module
>> >> >> >> >> > folder
>> >> >> >> >> > (so unique per module per ABI)
>> >> >> >> >> > 2) Gradle doesn't specify language level though you can
>> choose
>> >> >> >> >> > to
>> >> >> >> >> > specify it
>> >> >> >> >> > yourself from the build.gradle. This doc does a pretty good
>> job
>> >> >> >> >> > of
>> >> >> >> >> > explaining which variables are set by Gradle:
>> >> >> >> >> > https://developer.android.com/
>> ndk/guides/cmake.html#variables.
>> >> >> >> >> > Philosophically, we try to set as little as we can get away
>> >> >> >> >> > with.
>> >> >> >> >> > In
>> >> >> >> >> > particular, the section titled "Understanding the CMake
>> build
>> >> >> >> >> > command"
>> >> >> >> >> > lays
>> >> >> >> >> > out exactly what we set. You can also see the folders we
>> >> >> >> >> > specify
>> >> >> >> >> > (one
>> >> >> >> >> > per
>> >> >> >> >> > module per ABI)
>> >> >> >> >> > 3) Not sure I understand this.
>> >> >> >> >> >
>> >> >> >> >> > The other document worth taking a look at (if you haven't
>> >> >> >> >> > already)
>> >> >> >> >> > is:
>> >> >> >> >> >
>> >> >> >> >> > https://developer.android.com/
>> studio/projects/add-native-code.html
>> >> >> >> >> >
>> >> >> >> >> >
>> >> >> >> >> > On Mon, Aug 7, 2017 at 3:35 PM, Robert Dailey
>> >> >> >> >> > <rcdailey.lists at gmail.com>
>> >> >> >> >> > wrote:
>> >> >> >> >> >>
>> >> >> >> >> >> Thanks Jom
>> >> >> >> >> >>
>> >> >> >> >> >> Honestly, I prefer option 1 to work simply because that's
>> how
>> >> >> >> >> >> Google's
>> >> >> >> >> >> officially supporting CMake. But it also has debugging
>> which
>> >> >> >> >> >> is
>> >> >> >> >> >> the
>> >> >> >> >> >> #1
>> >> >> >> >> >> reason for me.
>> >> >> >> >> >>
>> >> >> >> >> >> However, I'd like to understand a lot more about how the
>> >> >> >> >> >> integration
>> >> >> >> >> >> really happens. For example, I have these questions:
>> >> >> >> >> >>
>> >> >> >> >> >> 1) How, internally, are CMake build directories managed? Do
>> >> >> >> >> >> you
>> >> >> >> >> >> generate 1 per unique android project? What about for each
>> >> >> >> >> >> specific
>> >> >> >> >> >> platform (x86, armeabi-v7a, etc)?
>> >> >> >> >> >> 2) Last time I looked into CMake integration, things
>> defined
>> >> >> >> >> >> inside
>> >> >> >> >> >> the CMake scripts were ignored because they are specified
>> at
>> >> >> >> >> >> the
>> >> >> >> >> >> command line. Namely, all of those settings that are
>> driven by
>> >> >> >> >> >> the
>> >> >> >> >> >> Gradle configuration (CXX language level was one in
>> particular
>> >> >> >> >> >> I
>> >> >> >> >> >> think; I specify C++14 support via CMake, but I recall this
>> >> >> >> >> >> being
>> >> >> >> >> >> overridden from outside)?
>> >> >> >> >> >> 3) How redundant is it to configure individual libraries
>> via
>> >> >> >> >> >> the
>> >> >> >> >> >> gradle scripts? In my previous attempts, I wanted to define
>> >> >> >> >> >> common
>> >> >> >> >> >> stuff for CMake / native code at the root gradle or
>> settings
>> >> >> >> >> >> file,
>> >> >> >> >> >> and
>> >> >> >> >> >> only define the differences in the actual gradle build
>> files
>> >> >> >> >> >> for
>> >> >> >> >> >> each
>> >> >> >> >> >> corresponding Java target (like, defining the name of the
>> >> >> >> >> >> native
>> >> >> >> >> >> (shared library) target in Gradle, but the command line
>> >> >> >> >> >> invocation,
>> >> >> >> >> >> -D
>> >> >> >> >> >> CMake settings, etc would all be common and defined at the
>> >> >> >> >> >> root).
>> >> >> >> >> >>
>> >> >> >> >> >> The TLDR is, the closer we can stay to CMake's way of doing
>> >> >> >> >> >> things
>> >> >> >> >> >> and
>> >> >> >> >> >> keep CMake-related settings self-contained to the CMake
>> >> >> >> >> >> scripts
>> >> >> >> >> >> themselves, the better. This also makes cross-platform
>> easier
>> >> >> >> >> >> (we
>> >> >> >> >> >> build the native code in Windows, for example, so having
>> >> >> >> >> >> settings
>> >> >> >> >> >> specified in the gradle files do not carry over to other
>> >> >> >> >> >> platforms.
>> >> >> >> >> >> Namely, settings that are not platform specific like the
>> C++
>> >> >> >> >> >> language
>> >> >> >> >> >> level).
>> >> >> >> >> >>
>> >> >> >> >> >> If there's a detailed document / wiki I can read on the
>> >> >> >> >> >> intrinsics
>> >> >> >> >> >> of
>> >> >> >> >> >> CMake integration in Gradle / Android Studio, I'd love to
>> read
>> >> >> >> >> >> it.
>> >> >> >> >> >> Otherwise, I hope you won't mind if I pick your brain as
>> >> >> >> >> >> questions
>> >> >> >> >> >> come up. I think I'm going to try option 1 for now and see
>> how
>> >> >> >> >> >> it
>> >> >> >> >> >> goes. It's just black box for me because unlike option 2, I
>> >> >> >> >> >> have
>> >> >> >> >> >> very
>> >> >> >> >> >> little control over what happens after building the shared
>> >> >> >> >> >> libraries,
>> >> >> >> >> >> and to make up for that I need to really get a deep
>> >> >> >> >> >> understanding
>> >> >> >> >> >> of
>> >> >> >> >> >> how it works so I can make sure I code my CMake scripts
>> >> >> >> >> >> properly
>> >> >> >> >> >> for
>> >> >> >> >> >> not only Android, but my other platforms as well
>> (non-Android
>> >> >> >> >> >> platforms).
>> >> >> >> >> >>
>> >> >> >> >> >> Thanks again.
>> >> >> >> >> >>
>> >> >> >> >> >> On Mon, Aug 7, 2017 at 5:12 PM, Jom O'Fisher
>> >> >> >> >> >> <jomofisher at gmail.com>
>> >> >> >> >> >> wrote:
>> >> >> >> >> >> > Either option can work fine. Disclosure: I work on
>> Android
>> >> >> >> >> >> > Studio
>> >> >> >> >> >> > and
>> >> >> >> >> >> > was
>> >> >> >> >> >> > the one that added CMake support.
>> >> >> >> >> >> >
>> >> >> >> >> >> > Option (1) is the way it's designed to work and we're
>> >> >> >> >> >> > working
>> >> >> >> >> >> > toward
>> >> >> >> >> >> > getting
>> >> >> >> >> >> > rid of the need for the CMake fork. I can't really say
>> when
>> >> >> >> >> >> > that
>> >> >> >> >> >> > will
>> >> >> >> >> >> > happen
>> >> >> >> >> >> > but if you can get away with an older CMake for now then
>> I'd
>> >> >> >> >> >> > go
>> >> >> >> >> >> > this
>> >> >> >> >> >> > way.
>> >> >> >> >> >> > As you mentioned, option (1) will allow you to view your
>> >> >> >> >> >> > source
>> >> >> >> >> >> > file
>> >> >> >> >> >> > structure in Android Studio, edit files, and debug using
>> the
>> >> >> >> >> >> > built-in
>> >> >> >> >> >> > debugging support.
>> >> >> >> >> >> >
>> >> >> >> >> >> > To get option (2) to work, you can use jniDirs setting to
>> >> >> >> >> >> > tell
>> >> >> >> >> >> > Android
>> >> >> >> >> >> > Gradle where to pick up your built .so files (see
>> >> >> >> >> >> >
>> >> >> >> >> >> >
>> >> >> >> >> >> >
>> >> >> >> >> >> >
>> >> >> >> >> >> >
>> >> >> >> >> >> > https://stackoverflow.com/ques
>> tions/21255125/how-can-i-add-so-files-to-an-android-library
>> -project-using-gradle-0-7).
>> >> >> >> >> >> > I'm not aware of any projects that use this approach but
>> it
>> >> >> >> >> >> > should
>> >> >> >> >> >> > work
>> >> >> >> >> >> > in
>> >> >> >> >> >> > principal.
>> >> >> >> >> >> >
>> >> >> >> >> >> > I hope this helps,
>> >> >> >> >> >> > Jomo
>> >> >> >> >> >> >
>> >> >> >> >> >> >
>> >> >> >> >> >> > On Mon, Aug 7, 2017 at 11:09 AM, Robert Dailey
>> >> >> >> >> >> > <rcdailey.lists at gmail.com>
>> >> >> >> >> >> > wrote:
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Right now I have custom targets set to execute the "ant
>> >> >> >> >> >> >> release"
>> >> >> >> >> >> >> command after my native targets are built. Part of that
>> >> >> >> >> >> >> command
>> >> >> >> >> >> >> involves copying *.so files to the libs/armeabi-v7a
>> >> >> >> >> >> >> directory
>> >> >> >> >> >> >> so
>> >> >> >> >> >> >> they
>> >> >> >> >> >> >> get packaged in an APK.
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> When switching to gradle, I have two options:
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> 1. Gradle drives CMake: This means using Android Studio
>> and
>> >> >> >> >> >> >> being
>> >> >> >> >> >> >> locked down to Google's fork of CMake which is a few
>> major
>> >> >> >> >> >> >> releases
>> >> >> >> >> >> >> behind. I see that as a negative.
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> 2. CMake drives Gradle: This would be the same or
>> similar
>> >> >> >> >> >> >> to
>> >> >> >> >> >> >> what
>> >> >> >> >> >> >> I'm
>> >> >> >> >> >> >> already doing: The custom targets I have would execute
>> >> >> >> >> >> >> gradle
>> >> >> >> >> >> >> as
>> >> >> >> >> >> >> a
>> >> >> >> >> >> >> separate build step, instead of running ant commands.
>> I'm
>> >> >> >> >> >> >> not
>> >> >> >> >> >> >> too
>> >> >> >> >> >> >> familiar with Gradle, so I'm not sure how you tell it
>> where
>> >> >> >> >> >> >> your
>> >> >> >> >> >> >> shared libraries are for the APK packaging steps.
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Which does everyone recommend? Is anyone using one of
>> these
>> >> >> >> >> >> >> setups
>> >> >> >> >> >> >> successfully? The downside to option 2 is probably no
>> >> >> >> >> >> >> on-device
>> >> >> >> >> >> >> native
>> >> >> >> >> >> >> debugging since Android Studio probably can't handle
>> gradle
>> >> >> >> >> >> >> projects
>> >> >> >> >> >> >> without any external CMake builds set up.
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Would like some general direction & advice before I move
>> >> >> >> >> >> >> away
>> >> >> >> >> >> >> from
>> >> >> >> >> >> >> ANT. Thanks in advance.
>> >> >> >> >> >> >> --
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Powered by www.kitware.com
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Please keep messages on-topic and check the CMake FAQ
>> at:
>> >> >> >> >> >> >> http://www.cmake.org/Wiki/CMake_FAQ
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Kitware offers various services to support the CMake
>> >> >> >> >> >> >> community.
>> >> >> >> >> >> >> For
>> >> >> >> >> >> >> more
>> >> >> >> >> >> >> information on each offering, please visit:
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> CMake Support: http://cmake.org/cmake/help/support.html
>> >> >> >> >> >> >> CMake Consulting:
>> >> >> >> >> >> >> http://cmake.org/cmake/help/consulting.html
>> >> >> >> >> >> >> CMake Training Courses:
>> >> >> >> >> >> >> http://cmake.org/cmake/help/training.html
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Visit other Kitware open-source projects at
>> >> >> >> >> >> >> http://www.kitware.com/opensource/opensource.html
>> >> >> >> >> >> >>
>> >> >> >> >> >> >> Follow this link to subscribe/unsubscribe:
>> >> >> >> >> >> >> http://public.kitware.com/mailman/listinfo/cmake
>> >> >> >> >> >> >
>> >> >> >> >> >> >
>> >> >> >> >> >
>> >> >> >> >> >
>> >> >> >> >
>> >> >> >> >
>> >> >> >
>> >> >> >
>> >> >
>> >> >
>> >
>> >
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/cmake/attachments/20170821/1c372039/attachment-0001.html>


More information about the CMake mailing list