19

I have Android Gradle + CMake (NDK) project with multiple flavors. C++ source files / libraries in subprojects are unnecessarily rebuilt after switching to flavor which was not built previously. Which is kind a expected giving that output folder is flavor specific and doesn't exist when building for the 1st time:

./app/.externalNativeBuild/cmake/prodDebug/armeabi/libs/mylib/libmylib.a
./app/.externalNativeBuild/cmake/devDebug/armeabi/libs/mylib/libmylib.a

But I have lot of flavors and large libraries to build and don't want to rebuild C++ libraries which are not depending on flavor - there are libraries which should be same for every flavor when built. I tried to fix this by specifying different output directory, so that it's not depending on flavor:

add_subdirectory("libs/mylib" "${CMAKE_CURRENT_SOURCE_DIR}/libs/mylib/output")

Every flavor now shares same output directory of mylib library, but this time library is rebuild all the time when switching flavors. When using ordinary CMake without Gradle all works as expected. Is there any way to fix unnecessary rebuilds when compiling from Android Studio / Gradle?

EDIT1: Btw, rebuilds are done even if flavors don't specify any C++ flags etc - essentially they are same just different application/version name:

    dev {
        applicationIdSuffix ".dev"
        versionNameSuffix "-dev"
    }
    prod {
        applicationIdSuffix ".prod"
        versionNameSuffix "-prod"
    }

EDIT2: There's also another rebuild issue. When changing any CMakeLists.txt (also subproject ones) it triggers entire rebuild of tree - all parent projects, subprojects (even unrelated ones) are rebuilt. Currently this is a stopper to using Gradle/Android Studio for building NDK projects.

Zig Razor
  • 3,381
  • 2
  • 15
  • 35
jozols
  • 560
  • 7
  • 22

3 Answers3

0

You cannot specify the binary_dir outside of the current working directory, try to change below line

add_subdirectory("libs/mylib" "${CMAKE_CURRENT_SOURCE_DIR}/libs/mylib/output")

to

add_subdirectory("libs/mylib" my-bin-dir)

This will notify the correct file status, e.g. need to recompile or not, to CMake build tools.

shizhen
  • 12,251
  • 9
  • 52
  • 88
  • That doesn't help. Output folders are now: ./app/.externalNativeBuild/cmake/devDebug/x86/my-bin-dir and ./app/.externalNativeBuild/cmake/prodDebug/x86/my-bin-dir So when I change source in library which has code without dependencies on flavor (prod/dev) it still builds changed source files twice (1st time for prod, 2nd time for dev) when I run ./gradlew :app:assembleProdDebug and ./gradlew :app:assembleDevDebug. In reality I have more than just 2 flavors and more than just one library. – jozols Dec 13 '18 at 10:56
  • Oops, surprised to hear that. But this work well for my project, every time I sync project, only the selected build variant got built. – shizhen Dec 13 '18 at 11:19
  • That might be true also for me. But for me problem is that there are files which are common for all flavors and they are rebuilt for all flavors when there is change in them. – jozols Dec 13 '18 at 12:20
0

Use ccache.

You can configure it in the CMakeLists.txt

I explain it at the bottom of this article:

https://medium.com/swlh/cross-platform-mobile-and-web-development-with-c-explained-8fb5fb916d35

This way you avoid the bug of Android studio and save time in general.

stephane k.
  • 1,668
  • 20
  • 21
0

I solved it by adding CCache to my CMakeLists.txt:

find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
    set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)

As described here:

https://stackoverflow.com/a/24305849/408877

Paul Slocum
  • 1,454
  • 13
  • 18