"generate_jni" targets should carry the necessary Java deps to the resulting APK |
|
Issue description
The issue; consider this example of a GN Android app:
android_apk("my_apk") {
shared_libraries = [":native_lib"]
# What we have to do now is this
deps = [":java_lib"]
}
shared_library("native_lib") {
sources = [
"foo.cc", # calls into Foo.java through JNI
]
deps = [":jni_headers"]
}
generate_jni("jni_headers") {
sources = ["Foo.java"]
# I want to be able to do something like this
# deps = [":java_lib"]
}
android_library("java_lib") {
java_files = ["Foo.java"]
}
In this example, native code for our Android app calls some Java code through generated JNI headers. The java code in "java_lib" isn't used except through JNI, so I want to make it a dependency of "jni_headers". The issue with this is, as it works right now, GN won't include the output of compiling "Foo.java" in the resulting APK unless "java_lib" is in the APKs deps, or is a transitive dependency through a chain of "android_library" targets. This means we have to declare dependencies in places where there aren't actual direct dependencies, and if we don't include "Foo.java" in this way, we get a runtime error when we try to use methods defined in "Foo.java".
I would like some way of declaring a dependency on a target like "generate_jni" that will cause the relevant Java dependency to be carried through all the source_sets to a shared_library target, and picked up by the android_apk target and included in the resulting APK.
,
Jan 14
Could the Java targets be listed as runtime dependencies of the generate_jni targets? Java libraries are loaded at runtime, just like shared libraries and data files that get put into data_deps.
,
Jan 14
For desktop java uses that might work, but on Android, Java libraries must be whole-program-optimized at the android_apk level by proguard, then converted into .dex format which runs on devices.
,
Jan 16
What would happen if we just added the data deps of the shared_libraries in an apk target to the apk's deps before sending the Java deps to proguard?
,
Yesterday
(44 hours ago)
data_deps are not guaranteed to be built before the target that depends on them.
,
Yesterday
(30 hours ago)
Yeah, but my understanding is that Java libraries don't need to have been built for the generate_jni() targets to do their thing (which is why they don't declare dependencies on them at all at the moment). It seems like the android_apk_or_module gn template already reads the transitive runtime deps of its invoker.shared_libraries to make sure all the necessary libraries are included for the component build. https://cs.chromium.org/chromium/src/build/config/android/rules.gni?q=rules.gni&sq=package:chromium&g=0&l=2093 What I'm trying to ask in comment #4 is: would it be possible to extend this to additionally grep the shared_libraries runtime_deps list for the Java libraries?
,
Today
(18 hours ago)
Hmm, I think I see what you're saying. If the native library declared thems as both a data dep, and a regular dep, then that should be enough to ensure it's built before the apk step. It's really not what data_dep is meant to be for, and would have the side-effect of isolates for swarmed tests pushing up all .jar files separately. We could probably just blanket filter those out though. I'm still quite wary of the idea though. We're currently trying to figure out building apps as modules, as well as building trichrome, where one apk has the native code, but the java code is split between three different apks. The extra complexity of this approach might be worse than the problem it's trying to solve.
,
Today
(17 hours ago)
The idea is that the native library would NOT declare the java library as a direct dep, but ONLY as a data dep. The android_apk_or_module gn template would then read the runtime deps of the shared_libraries it is given, the way it already does to find the transitive shared library dependencies, and adds those to the apk's deps. So the native library doesn't require the java library to be built, but an apk that includes the native library does need the java library to be built. Though I don't know enough about trichrome to know if that introduces too much added complexity. The problem this is trying to solve is that when we declare e.g. a unittest target, we need to have to add a bunch of java libraries in an if (is_android) clause if any of the native code calls into java code on Android. You have to find these java libraries by looking at all the native code and seeing if they include any generate_jni deps, and then find the corresponding android_library target for those generate_jni deps. We've had many cases where someone added a generate_jni target but didn't update the test target for the native code, and the unittests would crash at runtime.
,
Today
(16 hours ago)
You'd need to also add it as a regular dep as well, or else it might not be built by the time the apk step tries to execute. This is how the other usage of write_runtime_deps works. We could add a validation step that asserts at build time that there are no missing JNI symbols. Maybe that would be better? |
|
►
Sign in to add a comment |
|
Comment 1 by agrieve@chromium.org
, Jan 14