[CMake] CMake + Gradle for Android

Robert Dailey rcdailey.lists at gmail.com
Mon Aug 21 14:20:03 EDT 2017


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/questions/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
>> >> >> >> >
>> >> >> >> >
>> >> >> >
>> >> >> >
>> >> >
>> >> >
>> >
>> >
>
>


More information about the CMake mailing list