Andi McClure
2018-10-05 02:31:22 UTC
Short version: I have constructed a gradle NDK project where the main
project uses ndkBuild and a subproject uses CMake. I want the CMake project
to produce a library the ndkBuild project links, but the dependency to the
CMake project is not being applied, the library is not found by the main
project, and I do not know how to specify to the main project the filename
itâs supposed to be extracting from the CMake project.
Context: I have an existing video game which I am porting to the Oculus
Mobile SDK 1.16.0
https://developer.oculus.com/downloads/package/oculus-mobile-sdk/ . This
SDK contains libraries and sample code, both of which are built using
Gradle and ndkBuild. The SDKâs ndkBuild scripts for the sample projects are
pretty complicated and I do not know enough about how Oculus works to port
them to CMake myself. Meanwhile the project I am porting is based on CMake
and would be *very* difficult or impossible to port to ndkBuild, since it
includes CMake builds of very complex projects such as Assimp and LuaJIT.
For this reason, it is necessary I use both CMake and ndkBuild in this
single project.
Mixing CMake and ndkBuild in one build.gradle turns out to be not allowed (
it produces an error
https://android.googlesource.com/platform/tools/base/+/studio-2.2-preview3/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeBuildTaskUtils.java#179
). But what I *can* do is create a project and a subproject, and have one
use ndkBuild and the other CMake.
Currently my project is based on the VrCubeWorld_Framework example from the
Oculus Mobile SDK. Its dependencies {} section depends on five projects,
four Oculus libraries (:VrAppFramework:Projects:Android, etc) and one mine
(âimplementation project(':cmakelibâ)â). :cmakelib is a project at the top
of my repository. Its build.gradle is simple (attached). It includes a
CMakeLists.exe which builds a library named âlovrâ, created with CMake
add_library(lovr SHARED ${SOURCES}). I am using command line gradlew to
compile because I could not get Android Studio to create a project without
errors.
Some of what is happening makes sense to me:
1. I can build cmakelib by itself with "gradlew installDebugâ and it builds
and uploads an apk that is (unsurprisingly) not a valid Android program,
but if I unzip it, I can see it contains a file in lib/[ARCH] named
liblovrd.so.
2. I can build VrCubeWorld_Framework with âgradlew installDebugâ and it
builds and uploads an apk which is a valid Android program I can execute on
my Oculus Go, *and* if I unzip the APK I can see it contains that same
lib/[ARCH]/liblovrd.so.
Some of what is happening does *not* make sense to me, and is very bad:
1. Although builds of VrCubeWorld_Framework are triggering builds of
cmakelib, as if it were a dependency, the builds of cmakelib are not
occurring âbeforeâ the build of VrCubeWorld_Framework, as you would expect
for a dependency.
What I mean by this: Say that I introduce a failure into cmakelib, for
example I add âmessage(FATAL_ERROR test)â to the CMakeLists.txt. When I
installDebug the VRCubeWorld_Framework project, it will fail with the
expected message. But letâs say that I introduce failures to cmakelib and
VRCubeWorld_Framework at once (I put an error in the source file listed in
VRCubeWorld_Frameworkâs jni/Android.mk). VRCubeWorld_Framework will be
built first, and will print its error, and the build will halt, and
cmakelib will not be attempted. It appears VRCubeWorld_Framework compiles
first and cmakelib after.
This is especially a problem because:
2. VRCubeWorld_Framework, when its jni/Android.mk is being built, cannot
find liblovrd.so, and the symbols in liblovrd.so are not visible to its
source files. There is a symbol bridgeLovrInit(); in liblovrd.so. If I add
âlovrâ to LOCAL_SHARED_LIBRARIES in VRCubeWorld_Frameworkâs jni/Android.mk,
and add a call to bridgeLovrInit() in the VRCubeWorld_Frameworkâs main cpp
file, then build, I get these errors at the end of the gradlew output:
/Users/mcc/Library/Android/sdk/ndk-bundle/build/core/build-binary.mk:688:
Android NDK: Module vrcubeworld depends on undefined modules: lovr
[arm64-v8a] Compile++ : vrcubeworld <= VrCubeWorld_Framework.cpp
[arm64-v8a] Prebuilt : libvrapi.so <=
/Users/mcc/work/h/ovr_sdk_mobile_1.16.0/VrSamples/VrCubeWorld_Framework/Projects/Android/jni/../../../../../VrApi/Projects/AndroidPrebuilt/jni/../../../Libs/Android/arm64-v8a/Debug/
[arm64-v8a] SharedLibrary : libvrcubeworld.so
/Users/mcc/work/h/ovr_sdk_mobile_1.16.0/VrSamples/VrCubeWorld_Framework/Projects/Android/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/vrcubeworld/__/__/__/Src/VrCubeWorld_Framework.o:
In function `OVR::VrCubeWorld::EnteredVrMode(OVR::ovrIntentType, char
const*, char const*, char const*)':
/Users/mcc/work/h/ovr_sdk_mobile_1.16.0/VrSamples/VrCubeWorld_Framework/Projects/Android/jni/../../../Src/VrCubeWorld_Framework.cpp:116:
undefined reference to `bridgeLovrInit()'
clang++: error: linker command failed with exit code 1 (use -v to see
invocation)
Notice the warning on the first line and the error on the final line.
Other things which do not work: If I name lovr in the
LOCAL_SHARED_LIBRARIES line to âliblovrâ, it fails the same way, with the
âundefined module lovrâ error; if I say âliblovrdâ it gives me an error of
âundefined module lovrdâ. If I construct âlovrâ as a static library (I
would actually rather it be static) it canât find it like that either.
What am I supposed to do here? The other shared libraries included by
Android.mk are also coming out of subprojects, but those are all ndkBuild
based subprojects. It feels like some kind of magic is allowing the
ndkBuild projects to see each other which is not working when the
subproject is cmake. How are projects and subprojects in gradle supposed to
communicate outputs/inputs to each other?
project uses ndkBuild and a subproject uses CMake. I want the CMake project
to produce a library the ndkBuild project links, but the dependency to the
CMake project is not being applied, the library is not found by the main
project, and I do not know how to specify to the main project the filename
itâs supposed to be extracting from the CMake project.
Context: I have an existing video game which I am porting to the Oculus
Mobile SDK 1.16.0
https://developer.oculus.com/downloads/package/oculus-mobile-sdk/ . This
SDK contains libraries and sample code, both of which are built using
Gradle and ndkBuild. The SDKâs ndkBuild scripts for the sample projects are
pretty complicated and I do not know enough about how Oculus works to port
them to CMake myself. Meanwhile the project I am porting is based on CMake
and would be *very* difficult or impossible to port to ndkBuild, since it
includes CMake builds of very complex projects such as Assimp and LuaJIT.
For this reason, it is necessary I use both CMake and ndkBuild in this
single project.
Mixing CMake and ndkBuild in one build.gradle turns out to be not allowed (
it produces an error
https://android.googlesource.com/platform/tools/base/+/studio-2.2-preview3/build-system/gradle-core/src/main/java/com/android/build/gradle/tasks/ExternalNativeBuildTaskUtils.java#179
). But what I *can* do is create a project and a subproject, and have one
use ndkBuild and the other CMake.
Currently my project is based on the VrCubeWorld_Framework example from the
Oculus Mobile SDK. Its dependencies {} section depends on five projects,
four Oculus libraries (:VrAppFramework:Projects:Android, etc) and one mine
(âimplementation project(':cmakelibâ)â). :cmakelib is a project at the top
of my repository. Its build.gradle is simple (attached). It includes a
CMakeLists.exe which builds a library named âlovrâ, created with CMake
add_library(lovr SHARED ${SOURCES}). I am using command line gradlew to
compile because I could not get Android Studio to create a project without
errors.
Some of what is happening makes sense to me:
1. I can build cmakelib by itself with "gradlew installDebugâ and it builds
and uploads an apk that is (unsurprisingly) not a valid Android program,
but if I unzip it, I can see it contains a file in lib/[ARCH] named
liblovrd.so.
2. I can build VrCubeWorld_Framework with âgradlew installDebugâ and it
builds and uploads an apk which is a valid Android program I can execute on
my Oculus Go, *and* if I unzip the APK I can see it contains that same
lib/[ARCH]/liblovrd.so.
Some of what is happening does *not* make sense to me, and is very bad:
1. Although builds of VrCubeWorld_Framework are triggering builds of
cmakelib, as if it were a dependency, the builds of cmakelib are not
occurring âbeforeâ the build of VrCubeWorld_Framework, as you would expect
for a dependency.
What I mean by this: Say that I introduce a failure into cmakelib, for
example I add âmessage(FATAL_ERROR test)â to the CMakeLists.txt. When I
installDebug the VRCubeWorld_Framework project, it will fail with the
expected message. But letâs say that I introduce failures to cmakelib and
VRCubeWorld_Framework at once (I put an error in the source file listed in
VRCubeWorld_Frameworkâs jni/Android.mk). VRCubeWorld_Framework will be
built first, and will print its error, and the build will halt, and
cmakelib will not be attempted. It appears VRCubeWorld_Framework compiles
first and cmakelib after.
This is especially a problem because:
2. VRCubeWorld_Framework, when its jni/Android.mk is being built, cannot
find liblovrd.so, and the symbols in liblovrd.so are not visible to its
source files. There is a symbol bridgeLovrInit(); in liblovrd.so. If I add
âlovrâ to LOCAL_SHARED_LIBRARIES in VRCubeWorld_Frameworkâs jni/Android.mk,
and add a call to bridgeLovrInit() in the VRCubeWorld_Frameworkâs main cpp
file, then build, I get these errors at the end of the gradlew output:
/Users/mcc/Library/Android/sdk/ndk-bundle/build/core/build-binary.mk:688:
Android NDK: Module vrcubeworld depends on undefined modules: lovr
[arm64-v8a] Compile++ : vrcubeworld <= VrCubeWorld_Framework.cpp
[arm64-v8a] Prebuilt : libvrapi.so <=
/Users/mcc/work/h/ovr_sdk_mobile_1.16.0/VrSamples/VrCubeWorld_Framework/Projects/Android/jni/../../../../../VrApi/Projects/AndroidPrebuilt/jni/../../../Libs/Android/arm64-v8a/Debug/
[arm64-v8a] SharedLibrary : libvrcubeworld.so
/Users/mcc/work/h/ovr_sdk_mobile_1.16.0/VrSamples/VrCubeWorld_Framework/Projects/Android/build/intermediates/ndkBuild/debug/obj/local/arm64-v8a/objs-debug/vrcubeworld/__/__/__/Src/VrCubeWorld_Framework.o:
In function `OVR::VrCubeWorld::EnteredVrMode(OVR::ovrIntentType, char
const*, char const*, char const*)':
/Users/mcc/work/h/ovr_sdk_mobile_1.16.0/VrSamples/VrCubeWorld_Framework/Projects/Android/jni/../../../Src/VrCubeWorld_Framework.cpp:116:
undefined reference to `bridgeLovrInit()'
clang++: error: linker command failed with exit code 1 (use -v to see
invocation)
Notice the warning on the first line and the error on the final line.
Other things which do not work: If I name lovr in the
LOCAL_SHARED_LIBRARIES line to âliblovrâ, it fails the same way, with the
âundefined module lovrâ error; if I say âliblovrdâ it gives me an error of
âundefined module lovrdâ. If I construct âlovrâ as a static library (I
would actually rather it be static) it canât find it like that either.
What am I supposed to do here? The other shared libraries included by
Android.mk are also coming out of subprojects, but those are all ndkBuild
based subprojects. It feels like some kind of magic is allowing the
ndkBuild projects to see each other which is not working when the
subproject is cmake. How are projects and subprojects in gradle supposed to
communicate outputs/inputs to each other?
--
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk+***@googlegroups.com.
To post to this group, send email to android-***@googlegroups.com.
Visit this group at https://groups.google.com/group/android-ndk.
To view this discussion on the web visit https://groups.google.com/d/msgid/android-ndk/f0a97366-1d91-4396-9f31-e0afe457d629%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
You received this message because you are subscribed to the Google Groups "android-ndk" group.
To unsubscribe from this group and stop receiving emails from it, send an email to android-ndk+***@googlegroups.com.
To post to this group, send email to android-***@googlegroups.com.
Visit this group at https://groups.google.com/group/android-ndk.
To view this discussion on the web visit https://groups.google.com/d/msgid/android-ndk/f0a97366-1d91-4396-9f31-e0afe457d629%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.