I have a frontend and a backend repository for my app. The backend is written in Go and serves the API over gRPC. The generated gRPC Java files end up in backend-repo/proto-gen/java/ (so backend-repo/proto-gen/java/com/myApp/Users.java).
In my frontend android repo I have submoduled the backend repo to a folder called server. I want to modify my build.gradle to compile the .java files from the backend.
android-repo/
app/
build.gradle
server/proto-gen/java/com/myApp/
Users.java
AnotherService.java
I'm very new to Android development and am struggling to figure out the right approach.
This is a snippet from my app/build.gradle but it fails because it can't find the package com.google.protobuf.
task compileGrpc (type: JavaCompile) {
source = fileTree(dir: '../server/proto-gen/java/', include: '**/*.java')
destinationDir = file('build/classes')
classpath = files('../server/proto-gen/java/')
options.compilerArgs = ["-sourcepath", "$projectDir/../server/proto-gen/java/"]
}
dependencies {
compile 'com.google.protobuf:protobuf-java:3.0.0-alpha-2'
compileGrpc.execute()
}
You can add your dependencies like
dependencies {
classpath files('server/proto-gen/java/com/myApp/')
}
This will accept relative path.
Simply including the path to the src sourceset for the project would include them within the compilation:
android {
...
sourceSets {
main {
java.srcDirs = [java.srcDirs, 'server/proto-gen/java']
}
}
}
You'll be able to see the src files/directories included within the Android View/Project Explorer on the right side and edit the files directly.
Related
I'm new to Gradle and finding the documentation confusing.
I've downloaded the Jaunt webscraping API, however I can't seem to add it to my project. When downloaded, Jaunt is a folder that contains the jauntx.x.x.jar file inside it as a root for the library. In a normal IntelliJ project, I would simply add a reference to that .jar file.
However, I'm using Gradle as this project requires being built into an executable jar
I need to add the Jaunt library to the project but if I do it the normal way my project recognises the library while I'm developing it but as soon as I try to run it, it tells me that the com.jaunt package is not found.
I assume that it needs to be added to the build.gradle file, however I'm not sure how.
Can anyone advise?
Build.gradle as follows:
plugins {
id 'application'
id 'org.openjfx.javafxplugin' version '0.0.8'
}
repositories {
mavenCentral()
}
dependencies {
implementation files("libs/jaunt1.6.0.jar")
}
javafx {
version = "14"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
jar {
manifest {
attributes 'Main-Class': 'org.openjfx.Main'
attributes 'Class-Path': 'org/openjfx/ '
}
}
application {
mainClassName = 'org.openjfx.Main'
}
Using gradle 5.4 with a project dependency from external folder in a netbeans project.
The external folder contains resources like images, xml and custom objects that can only be created by this netbeans project. These external assets are then used to create binary files that get packed into a separate jar by that netbeans project.
These same external resources are also used during runtime for development in the gradle project. While I need the resources for development in the gradle project, I do not need or want them to be included in any jars anywhere for any reason when using the task build command because only the binaries are needed for distribution.
How to exclude the external resources from any and all jar files in the gradle project but allow them to be used for the classPath so I can run the project?
Some code examples of failure.
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'idea'
sourceSets {
main {
resources {
srcDir '../ExternalResourceFolder/assets'
}
}
}
jar {
exclude('../ExternalResourceFolder/assets/**')
}
dependencies {
runtimeOnly files('../ExternalResourceFolder/assets')
}
jar {
exclude('../ExternalResourceFolder/assets/**')
}
distributions {
main {
contents {
exclude '../ExternalResourceFolder/assets/**'
}
}
}
Tried many more things like adding to classPath and exclude but it would just be clutter to add them. Changing from sourceSet to dependency only moves the problem around from "build/lib" folder to "build/distributions" folder.
Had to exclude per file type in the end.
sourceSets {
main {
resources {
srcDir '.'
exclude ('**/*.j3odata','**/*.mesh','**/*.skeleton',\
'**/*.mesh.xml','**/*.skeleton.xml','**/*.scene',\
'**/*.material','**/*.obj','**/*.mtl','**/*.3ds',\
'**/*.dae','**/*.blend','**/*.blend*[0-9]','**/*.bin',\
'**/*.gltf')
}
}
}
I am actually Trying to use OpenCV in Java based Gradle Project. Since, OpenCV needs native library and Jar File for execution. I am trying to wrap native library and Jar together using gradle, but I am facing errors in doing so.
When I try to run project, project is not able to find native library for opencv jar and giving me below error
Exception in thread "main" java.lang.UnsatisfiedLinkError: no opencv_java340 in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at Library.(Library.java:9)
Although, I know how to set native library manually in Gradle project but I am not sure how to do it via Gradle and wrap native library in fat jar. Here is my build.gradle
// Apply the java-library plugin to add support for Java Library
apply plugin: 'java-library'
// In this section you declare where to find the dependencies of your project
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
}
configurations {
// configuration that holds jars to include in the jar
openCVLibs
}
dependencies {
openCVLibs fileTree(dir: 'libs', include: '*.jar')
openCVLibs fileTree(dir: 'libs', include: '*.so')
configurations.compile.extendsFrom(configurations.openCVLibs)
}
jar {
from {
configurations.openCVLibs.collect { it.isDirectory() ? it : zipTree(it) }
}
manifest {
attributes('Implementation-Title': project.name,
'Implementation-Version': project.version)
}
}
have also included link of sample eclipse project
So Here is edit
Based on #kerry's comment I tried to crate mvn artifact following openCV Maven, but now I am facing following error while creating mvn build
[ERROR] Failed to execute goal
org.codehaus.mojo:properties-maven-plugin:1.0.0:read-project-properties
(set-arch-properties) on project opencv: Properties could not be
loaded from File: /media/nitish/8EE47633E4761E21/opencv-3.4.0/build/build.properties -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to
execute goal
org.codehaus.mojo:properties-maven-plugin:1.0.0:read-project-properties
(set-arch-properties) on project opencv: Properties could not be
loaded from File: /media/nitish/8EE47633E4761E21/opencv-3.4.0/build/build.properties
There is no build.properties file present in build folder. Since build folder is created by maven task only, so build.properties file should be created by maven only.
Following there is a working example of a build.gradle file. Make sure to read the comments and make changes when appropriate.
By running gradle fatJar you can create a working Java Jar of your application with OpenCV inside.
However, apart form including your OpenCV library in your Java Jar, you will need to load the OpenCV native file at the beginning of your code.
They are two ways to do that:
1) Load the file by providing the full path:
System.load("my/full/path/opencv.dll");
2) If your native file is located inside your Java Library Path:
System.loadLibrary("opencv");
Take notice that in the second case you only need to provide the name of your native file (without its extension).
The default Java Library Path depends on OS:
On Windows, it maps to PATH
On Linux, it maps to LD_LIBRARY_PATH
On OS X, it maps to DYLD_LIBRARY_PATH
If you want to set your own Java Library Path:
try {
System.setProperty("java.library.path","YOUR/PATH");
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (Exception ex) {
System.out.println("Failed to set Java Library Path: " + ex.getMessage);
}
build.gradle
apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'application'
mainClassName = "YourMainClass" // You Main Class name
repositories{
mavenCentral()
}
task fatJar(type: Jar) {
manifest.from jar.manifest
classifier = 'all'
from {
configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
exclude "build/libs/philipath/**"
}
with jar
}
artifacts {
archives fatJar
}
dependencies {
// Local libraries
compile fileTree('lib') // assuming there is a folder named 'lib' in your project root with your OpenCV jar inside
// other dependencies
}
So I have a multi project setup that looks something like this
Root Project
--> common
--> project1
--> project2
--> 3rd_party_api
So common obviously contains a bunch of code shared across the other projects. Projects 1 and 2 are fine because they are wars and contain the common jar file as a dependency without any issues.
The problem I have is with my 3rd_party_api project. This is quite a small jar file that we will be delivering to other teams so that they can integrate with our code. Most of the java code required is contained in this project folder however there are 3 or 4 classes that are in the common project and need to be included in this library. Because it has to be standalone I need to wrap those classes in the jar file.
I have tried various iterations of srcDirs and source but I can't for the life of me figure out an easy way to do this.
As I've said I've looked at different approaches but my latest attempt looked a bit like this:
project(':api') {
defaultTasks 'jar'
apply plugin: 'java'
sourceSets {
main {
java {
srcDir 'src/main/java'
srcDir fileTree(dir: '../common/src/main/java').matching { include 'com/my/classes/**' }
}
}
dependencies {
compile project(':common')
}
}
This compiles successfully but the extra classes from common are not included in the jar.
Any help would be greatly appreciated.
Thanks Dirk,
Didn't quite work for me but got me thinking about other approaches. I eventually got it to do what I needed using a custom jar task. Something like the following:
defaultTasks 'lib'
dependencies {
compile project(':common')
}
task lib( type: Jar, dependsOn: classes) {
from sourceSets.main.output
from (project(':common').sourceSets.main.output) {
include 'com/myclasses/stuff/**'
include 'com/specificclass/MyClass.class'
}
}
maybe something like:
jar {
baseName = 'yourJarFileName'
from('path/to/your/dir/') {
include 'local/path/from/there/**/*.jar'
}
}
didn't checked this ... so don't blame me if it does not work out of the box ;)
other possibility would be to define your custom sourceSets ... but never tried this either.
In Eclipse I can add a source folder to my Android project as a "linked source folder". How do I achieve the same thing in Android Studio?
Or is it possible to add an external folder to build in Gradle?
In your build.gradle file, add the following to the end of the Android node:
android {
....
....
sourceSets {
main.java.srcDirs += 'src/main/<YOUR DIRECTORY>'
}
}
The right answer is:
android {
....
....
sourceSets {
main.java.srcDirs += 'src/main/<YOUR DIRECTORY>'
}
}
Furthermore, if your external source directory is not under src/main, you could use a relative path like this:
sourceSets {
main.java.srcDirs += 'src/main/../../../<YOUR DIRECTORY>'
}
You can add a source folder to the build script and then sync. Look for sourceSets in the documentation here: http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Basic-Project
I haven't found a good way of adding test source folders. I have manually added the source to the .iml file. Of course this means it will go away everytime the build script is synched.
While sourceSets allows you to include entire directory structures, there's no way to exclude parts of it in Android Studio (as of version 1.2), as described in Exclude a class from the build in Android Studio.
Until Android Studio gets updated to support include/exclude directives for Android sources, symbolic links work quite well. If you're using Windows, native tools such as junction or mklink can accomplish the equivalent of symbolic links on Unix-like systems. Cygwin can also create these with a little coercion. See: Git symbolic links in Windows and How to make a symbolic link with Cygwin in Windows 7.
Here’s a complete Java module Gradle file that correctly generates and references the built artefacts within an Android multi-module application:
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
}
dependencies {
classpath "net.ltgt.gradle:gradle-apt-plugin:0.15"
}
}
apply plugin: "net.ltgt.apt"
apply plugin: "java-library"
apply plugin: "idea"
idea {
module {
sourceDirs += file("$buildDir/generated/source/apt/main")
testSourceDirs += file("$buildDir/generated/source/apt/test")
}
}
dependencies {
// Dagger 2 and Compiler
compile "com.google.dagger:dagger:2.15"
apt "com.google.dagger:dagger-compiler:2.15"
compile "com.google.guava:guava:24.1-jre"
}
sourceCompatibility = "1.8"
targetCompatibility = "1.8"
This is for Kotlin DSL (build.gradle.kts):
android {
sourceSets["main"].java.srcDirs("src/main/myDirectory/code/")
sourceSets["main"].resources.srcDirs("src/main/myDirectory/resources/")
// Another notation:
// sourceSets {
// getByName("main") {
// java.srcDirs("src/main/myDirectory/code/")
// resources.srcDirs("src/main/myDirectory/resources/")
// }
// }
}
If you're not using Gradle (creating a project from an APK, for instance), this can be done through the Android Studio UI (as of version 3.3.2):
Right-click the project root directory and pick Open Module Settings
Hit the + Add Content Root button (center right)
Add your path and hit OK
In my experience (with native code), as long as your .so files are built with debug symbols and from the same absolute paths, breakpoints added in source files will be automatically recognized.