Hello my fellow developers,
I'm trying to switch from Gradle to Buck and have problems setting it up with Dagger and Butterknife since they need annotation processing.
I found a few links and tutorials, but they are already a few (~4) years old and I thought there might be a little bit newer approach on doing things.
This is what I looked at already:
https://github.com/ryan-endacott/android-buck-dagger-starter
Thanks in advance,
Patrick
Buck supports annotation processing for Java-based rules (including android_library). Take a look at how Immutables are used in buck repository (link to source code):
First of all, you need to declare library jars:
java_library(
name = "immutables",
exported_deps = [
":builder",
":value",
],
visibility = [
"PUBLIC",
],
)
prebuilt_jar(
name = "value",
binary_jar = "value-2.5.6.jar",
source_jar = "value-2.5.6-sources.jar",
licenses = [
"COPYING",
],
)
prebuilt_jar(
name = "builder",
binary_jar = "builder-2.5.6.jar",
source_jar = "builder-2.5.6-sources.jar",
licenses = [
"COPYING",
],
)
Define annotation processor:
java_annotation_processor(
name = "processor",
isolate_class_loader = True,
processor_class = "org.immutables.value.internal.$processor$.$Processor",
visibility = [
"PUBLIC",
],
deps = [
":immutables",
],
)
You can then add this annotation processor to the list of plugins of the targets:
java_library(
name = "target",
plugins = [
"//third-party/java/immutables:processor",
],
deps = [
...
],
...
)
Buck repository contains a custom rule (java_immutables_library) that adds this annotation processor so that developers don't need to specify plugins on every target. You can probably use similar approach.
Related
I've been using ConstraintLayout of version 1.1.2 for a while now. It was working perfectly. Then new MotionLayout came up and I thought why not to try it out. And everything seemed fine.
However I made a mistake of using it in production. Only after some time I noticed some bug reports on ConstraintLayout working not properly. But there are some screens already that depend on MotionLayout, removing which will cause a lot of refactoring.
Is it possible to use MotionLayout(v2.0.0-alpha-05/beta-02) and ConstraintLayout(v1.1.3) for the same project, so that screens that work with MotionLayout would have v2.0.0 and screens that work with ConstraintLayout only would have v1.1.3? Is there some packaging tool to move MotionLayout to a different package? I tried to use shadowJar gradle plugin but failed because MotionLayout is an *.aar dependency not *.jar.
Edit:
I've created a sample where I use jetifier gradle plugin from aosp to rewrite the package names and demonstrate how to use both 1.1.3 and 2.0.0-beta versions in the same project.
You can use jetifier with custom config file to rewrite package name. Just run it on both constraintlayout-2.0.0-beta2.aar and constraintlayout-solver-2.0.0-beta2.jar like this:
./jetifier-standalone -i constraintlayout-2.0.0-beta2.aar -o myconstraintlayout-2.0.0-beta2.aar -c config.json
./jetifier-standalone -i constraintlayout-solver-2.0.0-beta2.jar -o myconstraintlayout-solver-2.0.0-beta2.jar -c config.json
where config.json is the custom config like this:
{
"restrictToPackagePrefixes": [
"androidx/"
],
"reversedRestrictToPackagePrefixes": [],
"rules": [
{
"from": "androidx/(.*)",
"to": "myandroidx/{0}"
},
],
"packageMap": [
{
"from": "androidx/constraintlayout/widget",
"to": "myandroidx/constraintlayout/widget"
}
],
"pomRules": [],
"versions": {
"latestReleased": {}
},
"map": {
"types": {}
},
"proGuardMap": {
"rules": {
"androidx/{any}": [
"myandroidx/{any}"
]
}
},
"stringsMap": {
"types": {}
}
}
You can check the original config file to find out file format.
After that you can use myconstraintlayout-2.0.0-beta2.aar and myconstraintlayout-solver-2.0.0-beta2.jar in your project. Obviously you'll have to change package name for MotionLayout in your project.
It should be possible to automate the process by writing a gradle plugin also.
Edit: it's probably better to repackage constraintlayout-1.1.3, so you can easily update MotionLayout with new versions when they are released.
I faced similar issues - the only possible way to avoid the class collision is to rebuild one of the dependencies with the different package name. It could be done by downloading the code of one of the libraries and recompile it manually on your PC. For example from here.
But I would recommend you to use ConstraintLayout library version 2.0
implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta2'
or
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
if you are using AndroidX.
Is contains both ConstraintLayout and MotionLayout so they would not create a conflict in your code. Some small adjustments may be needed in your current code though.
Hope it helps.
I have been trying to import opencv-android-sdk to my Bazel project but I am not able to do it.
I tried the this answer on SO but while building my project I get errors that
error: package org.opencv.android does not exist
I see that there's an opencv-android artifact on Maven.
You can depend on this using rules_jvm_external.
In your WORKSPACE file, specify the dependency along with the other external dependencies:
load("#rules_jvm_external//:defs.bzl", "maven_install")
maven_install(
artifacts = [
"org.opencv:opencv-android:1.0.1",
# ...
],
repositories = [
"https://maven.google.com",
"https://jcenter.bintray.com",
],
)
Then, in your BUILD file containing your Android targets, depend on the OpenCV target:
android_library(
name = "my_lib",
custom_package = "com.example.bazel",
srcs = glob(["java/com/example/bazel/*.java"]),
manifest = "java/AndroidManifest.xml",
resource_files = glob(["res/**"]),
deps = [
"#maven//:org_opencv_opencv_android",
],
visibility = ["//src/test:__subpackages__"]
)
Finally, you should be able to reference classes like org.opencv.core.Core in your Android Java code.
P.S. consider switching all your maven_jar and gmaven_rules/gmaven_artifact to use rules_jvm_external. The former Maven rules have been deprecated in favor of rules_jvm_external.
I put react-native.jar to tensorflow android's directory and add configuration to tensorflow/examples/android/BUILD file like this:
java_import(
name = "react-native",
jars = [
"react-native-0.39.2-sources.jar",
],
)
Now run bazel build //tensorflow/examples/android:tensorflow_demo work well. But then use import com.facebook.react.*; in java file and run bazel build ... again, it throws a nonexistent error, can't find com.facebook.react.* package.
In order to expose the classes in the JAR to the Java code in the Android build, you need to add a dependency in the android_binary that you are building on the java_import you have created.
For example:
# tensorflow/examples/android/BUILD
java_import(
name = "react-native",
jars = [
"react-native-0.39.2-sources.jar",
],
)
android_binary(
name = "tensorflow_demo",
srcs = glob(["src/**/*.java"]),
deps = [
":tensorflow_native_libs",
"//tensorflow/contrib/android:android_tensorflow_inference_java",
":react-native",
],
)
I'm building an Android library based on Tensorflow with Bazel.
Here the BUILD file
cc_binary(
name = "libfoo.so",
srcs = glob([
"jni/**/*.cc",
"jni/**/*.h",
]),
copts = [ "-fexceptions", "-DEIGEN_AVOID_STL_ARRAY",
"-mfpu=neon", "-std=c++11",
"-DMIN_LOG_LEVEL=0", "-DTF_LEAN_BINARY",
"-O2", ],
linkopts = [
"-llog",
"-lm",
],
linkshared = 1,
deps = [
"#org_tensorflow//tensorflow/core:android_tensorflow_lib",
"#boringssl//:crypto",
],
)
The linker complains about not finding -lpthread, while I didn't add this flag to linkopts.
I've checked the executed command, and in fact there is extra flags on it: -lz -lpthread ...
Where did they came from ? Is there a workaround for this ?
I got the answer from the tensorflow's issue tracker.
#jart
Since copts and linkopts are viral and propagate to dependencies, -lpthread is most likely being inherited from #boringssl//:crypto
#andrewharp
-lpthread is not necessary or possible on Android, so it sounds like the solution would be to add another condition for the select statement as in the linked commit google/protobuf#1386:
...
The only other workaround I know of that doesn't require editing the other repository is to create a dummy libpthread.so target, but that's pretty hacky.
Related to this ticket Parameters for annotation processors are disabled and undocumented
How do we use annotation_processors and annotation_processor_deps ?
Im using realm in a sample Android app and without the annotations (for #RealmClass and #RealmMoudule) the app crashes when built via buck (works normally if built via gradle).
In case anyone stumbles on this, the way to use annotation processors with buckbuild is:
The annotation_processors is a immutable list of processor class. You can identify this by the package name used in META-INF/services/javax.annotation.processing.Processor file, example: Realm Processor
The annotation_processor_deps is a immutable list of Rules (generally prebuilt_jar or android_prebuilt_aar) holding the annotation processor
A sample buck build file of a project that uses Realm Java
prebuilt_jar(
name = 'realm',
binary_jar = 'libs/realm-android-0.82.2.jar'
)
android_library(
name = 'main-lib',
srcs = glob(['app/src/main/java/com/yourcompany/project/**/*.java']),
deps = [
':supportv4',
':all-jars',
':build-config',
':res',
],
annotation_processors = ['io.realm.processor.RealmProcessor'],
annotation_processor_deps = [':realm']
)