22

I'm using Gradle and CMake to compile an Android NDK project from the command line. Previously, I was using Ant and ndk-build but I'm trying to migrate the project completely to Gradle and CMake.

In my build.gradle I have the following lines to invoke CMake:

externalNativeBuild {
    cmake {
        path "src/main/cpp/CMakeLists.txt"
    }
}

Now how can I force CMake to print all compiler calls to the console before it makes them? Specifically, I want to see just how CMake runs the compiler and linker.

I've already tried the following, all to no avail:

1) In my CMakeLists.txt I have put the following line:

set(CMAKE_VERBOSE_MAKEFILE on)

Didn't have any effect.

2) I have started the build like this:

./gradlew build --info

Gradle printed some stuff, but no compiler calls.

3) And like this:

./gradlew build --debug

Gradle printed lots of stuff, but no compiler calls.

So none of those three attempts did what I wanted which makes me wonder how can I see how CMake runs clang on my individual source files?

Andreas
  • 9,245
  • 9
  • 49
  • 97
  • 1
    Check `.externalNativeBuild` directory under project root; it may contain all information relevant for you – Alex Cohn Apr 16 '17 at 18:49
  • 1
    Indeed, great, thanks! There's a `build.ninja` log file which contains all the essential information. If you want to post your comment as an answer, I'll accept it. – Andreas Apr 16 '17 at 18:57
  • See also some update: I finally reached my desktop to test the flags manually. – Alex Cohn Apr 19 '17 at 10:47

3 Answers3

43

Disclaimer: the following description applies to the version of Android Gradle Plugin (AGP) that was the latest at the time I updated this Answer (aug '21). If you are curious, have a look at the history of edits.

As @artyomd has noticed, for AGP 4.2.0 and higher, you can set android.native.buildOutput gradle property to verbose to force cmake logging.

In Android Studio, gradle creates directory .cxx under the module root, for each module that has NDK integration, via CMake or ndk-build.

For CMake, the gradle plugin is quite verbose. For each build variant it creates separate subdirectory, e.g. .cxx/cmake/debug/x86 or .cxx/cmake/release/armeabi-v7a, etc.

Each directory contains some useful files: cmake_build_command.txt describes the actual parameters passed to CMake; android_gradle_build.json shows what parameters the gradle plugin derived for your binaries; from build.ninja you can deduce the how these parameters were applied for each compilation or linkage step.

For ndk-build, the android_gradle_build.json file is also quite useful. ndkBuild_build_command.txt lists all parameters passed to ndk-build command, and ndkBuild_build_output.txt is the unabridged output of that command. You can easily add V=1 to the arguments, e.g.

externalNativeBuild {
  ndkBuild {
    cppFlags "-std=c++11"
    arguments "APP_STL=c++_static", "APP_OPTIM=release", "NDK_DEBUG=0", "V=1"
    abiFilters "armeabi-v7a"
  }
}

For CMake, the relevant argument is "-DCMAKE_VERBOSE_MAKEFILE=ON" (see explanation and alternatives):

externalNativeBuild {
  cmake {
    cppFlags "-std=c++11"
    arguments "-DCMAKE_VERBOSE_MAKEFILE=ON"
    abiFilters "armeabi-v7a"
  }
}

But, as @user7860670 has observed, the recent versions of AGP ignore this flag.

Without CMAKE_VERBOSE_MAKEFILE, the Gradle Console displays:

:app:externalNativeBuildDebug
Build native-lib armeabi-v7a
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so

With "-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON", I used to get tons of output:

:app:externalNativeBuildDebug
Build native-lib armeabi-v7a

[1/2] /Users/alex/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++  --target=armv5te-none-linux-androideabi --gcc-toolchain=/Users/alex/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 --sysroot=/Users/alex/Library/Android/sdk/ndk-bundle/platforms/android-14/arch-arm  -Dnative_lib_EXPORTS -isystem /Users/alex/Library/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include -isystem /Users/alex/Library/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include -isystem /Users/alex/Library/Android/sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include/backward -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security   -O0 -fno-limit-debug-info -O0 -fno-limit-debug-info  -fPIC -MD -MT CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -MF CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o.d -o CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o -c /Users/alex/test/egl/app/src/main/cpp/native-lib.cpp
[2/2] : && /Users/alex/Library/Android/sdk/ndk-bundle/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++  --target=armv5te-none-linux-androideabi --gcc-toolchain=/Users/alex/Library/Android/sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64 --sysroot=/Users/alex/Library/Android/sdk/ndk-bundle/platforms/android-14/arch-arm -fPIC -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security  -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv5te -mtune=xscale -msoft-float -fno-integrated-as -mthumb -Wa,--noexecstack -Wformat -Werror=format-security   -O0 -fno-limit-debug-info -O0 -fno-limit-debug-info  -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -Wl,--build-id -Wl,--warn-shared-textrel -Wl,--fatal-warnings -Wl,--no-undefined -Wl,-z,noexecstack -Qunused-arguments -Wl,-z,relro -Wl,-z,now -shared -Wl,-soname,libnative-lib.so -o ../../../../build/intermediates/cmake/debug/obj/armeabi-v7a/libnative-lib.so CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o  -llog -lEGL -lGLESv2 -lm "/Users/alex/Library/Android/sdk/ndk-bundle/sources/cxx-stl/llvm-libc++/libs/armeabi-v7a/libc++_static.a" "-latomic" && :

Not anymore. As far as I know, this information is filtered by Gradle Plugin and is completely lost. I can recover it only manually: run the command

/Users/alex/Library/Android/sdk/cmake/3.10.2.4988404/bin/cmake --build app/.cxx/cmake/debug/armeabi-v7a

You can use the Terminal window (Alt-F12) of Android Studio. This will invoke ninja with -v flag when -DCMAKE_VERBOSE_MAKEFILE=ON was used to sync C++ with Gradle.

Note that the expected file .cxx/cmake/debug/armeabi-v7a/cmake_build_output.txt does not contain interesting information (unless you have problems with CMake configuration per se).

P.S. with this 3.6.0 Gradle Plugin, if you have a compilation error, then the whole command line for compiler is shown in Build Output window, no matter whether you set CMAKE_VERBOSE_MAKEFILE or not. Actually, twice: once, in black on white (I don't use the dark theme), second time, in brown on white, after

FAILURE: Build failed with an exception.

* What went wrong:
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307
  • gives me an error: `Could not find method arguments() for arguments on object of type com.android.build.gradle.internal.dsl.CmakeOptions` – peetonn Jul 06 '17 at 19:50
  • 4
    @peetonn: your mistake is that you put it in the **externalNativeBuild** block with **path** to CMakeLists.txt; but **arguments** should go into the other block, which is inside **android.defaultConfig** – Alex Cohn Jul 06 '17 at 21:09
  • 7
    PS I cannot imagine the mindset that came up with the idea to give the same names to entirely different entities in android.build.gradle DSL – Alex Cohn Jul 06 '17 at 21:20
  • 3
    Note: `"-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"` does not seem to work anymore. `"-DCMAKE_VERBOSE_MAKEFILE=ON"` worked for me. Not sure what has changed, I just installed android studio. – Fake Name Oct 11 '17 at 21:21
  • @AlexCohn I am using android studio on Windows 10. I can't find any .externalNativeBuild directory under module root. The only directories it has are .cxx, build, libs,and src. Do I need to change some gradle flags so as to make it produce this directory? – Arpit Aggarwal Nov 19 '19 at 04:59
  • @ArpitAggarwal since this answer, the gradle plugin changed its naming convention. The directory that you see as `.cxx` was then called `.externalNativeBuild`. As far as I know, this did not change the internal logic of build process (*yet*). – Alex Cohn Nov 19 '19 at 13:41
  • 2
    `"-DCMAKE_VERBOSE_MAKEFILE:BOOL=ON"` is getting completely ignored (cmake server issues a corresponding warning), `"-DCMAKE_VERBOSE_MAKEFILE=ON"` does not seem to work anymore either – user7860670 Jan 11 '20 at 21:00
  • 1
    I set `"-DCMAKE_VERBOSE_MAKEFILE=ON"` and I found the compile commands in `.cxx/cmake//armeabi-v7a/compile_commands.json` file. – Peter Jan 26 '21 at 12:51
  • How can we change ".cxx" directory? – Top-Master May 27 '21 at 03:01
  • @Top-Master I don't think you can change the `.cxx` directory, but the question is: why should you? Most likely, there is a better way to satisfy your needs. – Alex Cohn May 28 '21 at 18:52
  • 1
    At last, to change build directory (recently named `.cxx`), found correct solution in [another thread](https://stackoverflow.com/a/60492487/8740349) with example!! see [CMake docs](https://developer.android.com/reference/tools/gradle-api/4.1/com/android/build/api/dsl/Cmake) and details. – Top-Master May 30 '21 at 03:40
  • 1
    starting from AGP 4.2.0 you can set **android.native.buildOutput gradle** property to **verbose** to force cmake logging. https://developer.android.com/studio/releases/gradle-plugin?hl=it-ch&skip_cache=true#native-build-output – artyomd Jul 31 '21 at 10:13
  • thanks @artyomd I have included your update in the answer! – Alex Cohn Aug 17 '21 at 15:34
  • How/where do you set it? I tried `./gradlew -Pandroid.native.buildOutput=verbose build, but it doesn't do anything... I am on the gradle plugin 7.3. – JonasVautherin Jan 13 '23 at 18:02
  • @JonasVautherin as you can see, the progress of AGP has changed this bit significantly over years. I am not sure how the desired level of verbosity can be achieved these days. – Alex Cohn Jan 15 '23 at 09:38
2

As an ugly workaround I've replaced ninja with my own executable that passes all the commands to the real ninja executable appending "-v"

user7860670
  • 35,849
  • 4
  • 58
  • 84
-5

Try to update your gradle version.

zhen She
  • 129
  • 1
  • 9