3

My build.gradle file contains this to build a project with CMake:

   externalNativeBuild {
    cmake {
        // Provides a relative path to your CMake build script.
        version "3.13.0+"
        path "../subproj/smcxx/CMakeLists.txt"
    }
}

The CMakeList.txt defines multiple targets, but the problematic one is this:

set(SOURCES "src/lib.cc")
add_library(smcxx_obj OBJECT ${SOURCES})

An OBJECT target would not build a .so or .a file, instead, the .o files can be used in other targets.

The problem is (from my understanding) that Gradle analyzes the CMake targets and expects an output file for each target. When I compile the whole project using gradlew, I get the following error message:

> Task :app:externalNativeBuildDebug FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:externalNativeBuildDebug'.
> Expected output file at /home/cytrinox/src/androidapp/app/.cxx/cmake/debug/armeabi-v7a/smcxx_obj for target smcxx_obj but there was none

The object file lib.cc.o was successfully compiled and exists. But there is no smcxx_obj folder nor a smcxx_obj.so file (which is expected).

Is it possible to solve this error, for example by telling Gradle to skip this check for a specific CMake target?

Kevin
  • 16,549
  • 8
  • 60
  • 74
cytrinox
  • 1,846
  • 5
  • 25
  • 46
  • Getting exactly the same problem. Did you manage to find a fix, short of dropping the object library target from the CMakeLists.txt? – Ivano.Bilenchi Jan 15 '20 at 18:43
  • @Ivano.Bilenchi I've removed the object library as a targt in cmake and used the object files in the other libs (static + shared) directly, instead of a object library target. But it's not a fix for the initial issue. – cytrinox Jan 22 '20 at 21:09
  • Your comment reminded me I actually found a decent fix. I added it as an answer. – Ivano.Bilenchi Jan 23 '20 at 10:55

1 Answers1

4

According to the documentation:

Gradle builds all executables and shared object libraries that you define in your CMake (or ndk-build) project.

However, CMake object libraries don't seem to be supported at all, and cause the issue you are experiencing. I actually believe this is a bug: Gradle should just skip building them, as they are mostly only useful within CMake itself.

Anyhow, you can fix this by manually specifying which CMake targets you want Gradle to build (e.g. just omit object library targets and you'll be fine):

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      ...
      cmake {
        targets "target1", "target2"
      }
    }
  }
OlivierM
  • 2,820
  • 24
  • 41
Ivano.Bilenchi
  • 501
  • 4
  • 14
  • Seems better because no modification to the cmake file ist required. – cytrinox Jan 23 '20 at 11:37
  • I didn't want to believe that this belongs under "defaultConfig" at first. Turns out I was wrong: https://cmake.org/pipermail/cmake/2017-August/066146.html – TomTasche Mar 19 '20 at 19:56
  • 2
    This solution does not work if, e.g. "target1" depends on `OBJECT` library. "target1" could still be a shared library or executable. – DoDo May 28 '21 at 18:06
  • I tried and it did not work for me. – BrunoLevy Nov 13 '21 at 16:16