I have read many similar questions where the reply is that the project structure is not ideal so my questions based on the following:
I have a main project (ProjA) which needs to include a second project (ProjB) which is not a child project. ProjB has various resource files which need to be copied in the distribution of ProjA.
build.gradle of ProjA
dependencies {
compile project(":ProjB")
}
distributions {
main {
baseName = "Something"
contents {
into('bin') { from jar.archivePath }
into('lib') { from configurations.runtime }
into('etc') {
from ('../../projb/src/main/webapp') // Fix me!
}
}
}
}
1.) Ideally ProjB should expose the location of the resource files through a property used by ProjA, how can this be done?
2.) Is this the correct way to do it as I have read alot about cross-project properties not being ideal - or should I be doing something completely different?
Don't know if it helps but it seems that the best way is to do it in the following way:
distributions {
main {
baseName = "Something"
contents {
into('bin') { from jar.archivePath }
into('lib') { from configurations.runtime }
into('etc') {
from project(':projB').file('src/main/webapp')
}
}
}
}
The path must be hardcoded in that case.
Second option might be specifying a project property - in general not a very good idea - and use in another project - there must be also evaluation order defined.
In projB
ext.resourcesDir = project.file('src/main/webapp2')
and in projA
evaluationDependsOn(':projB')
and:
distributions {
main {
baseName = "Something"
contents {
into('bin') { from jar.archivePath }
into('lib') { from configurations.runtime }
into('etc') {
from project(':projB').file('src/main/webapp')
from project(':projB').resourcesDir
}
}
}
}
Here's complete example.
Related
I am using the below configuration build.gradle
plugins {
id "com.google.protobuf" version "0.8.17"
id "java"
}
group "de.prerna.aws.tests"
version "1.0-SNAPSHOT"
repositories {
mavenCentral()
}
ext {
protobufVersion = "3.18.1"
}
dependencies {
implementation "com.google.protobuf:protobuf-java:$protobufVersion"
sourceSets {
main {
proto {
srcDir 'src/main/proto'
}
java {
// include self written and generated code
srcDirs 'src/main/java'
}
}
}
protobuf {
protoc {
artifact = 'com.google.protobuf:protoc:4.0.0-rc-2'
}
plugins {
grpc {
artifact = "io.grpc:protoc-gen-grpc-java:1.39.0"
}
}
generateProtoTasks.generatedFilesBaseDir = 'generated-sources'
generateProtoTasks {
all().each { task ->
task.plugins { grpc{} }
}
ofSourceSet('main')
}
}
Error
* What went wrong:
Execution failed for task ':processResources'.
> Entry Person.proto is a duplicate but no duplicate handling strategy has been set. Please refer to https://docs.gradle.org/7.2/dsl/org.gradle.api.tasks.Copy.html#org.gradle.api.tasks.Copy:duplicatesStrategy for details.
A variant of BParolini for build.gradle (Groovy DSL)
tasks.withType(Copy) {
filesMatching("**/*.proto") {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}
I could fix this problem by adding the following code to my build.gradle.kts:
tasks {
withType<Copy> {
filesMatching("**/*.proto") {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
}
}
}
Extra info: I'm using Gradle 7.3-rc-3 and Java 17.
Unfortunately nobody explains reasons for this problem, so here is some of my explorations and guesses. Please correct me if you know more.
If found that following build script code causes this error:
proto { srcDir 'src/main/proto' }
If look inside "build/extracted-include-protos" directory, there are original .proto files copied into "build/extracted-include-protos/test" (but not into main).
My guess is that those auto-copied .proto files are originally uses as the only sources, but when adding "src/main/proto" source set we give some compiler tool second set of same files.
Removing this srcDir is not a good idea, because it required for IDEA to correctly open included .proto on Ctrl+click (otherwise it is opened extracted copies which is useless).
This question was answered before but the chosen answer doesn't explain a lot for me on how this is doable on Gradle.
That and the fact that I can't comment on the solution to ask for more info forced me to make this question.
I have a Gradle project that has several modules available and I now want to set up the Javadoc task to combine the Javadoc comments of all the modules into a single location where I could browse it.
How would I now be able to do this using Gradle? I run Gradle 5.5 if the version is of any importance and I have the following things set in the build.gradle file:
allprojects {
ext {
// Convenience method to configure Javadoc
configureJavadoc = { Object jDocConfig ->
jDocConfig.options {
it.author()
it.encoding = 'UTF-8'
it.memberLevel = JavadocMemberLevel.PROTECTED
if (it instanceof StandardJavadocDocletOptions) {
def opt = it as StandardJavadocDocletOptions
opt.links(
"https://docs.example.com/java/"
)
if (JavaVersion.current().isJava9Compatible()) {
opt.addBooleanOption("html5", true)
opt.addStringOption("-release", "8")
}
if (JavaVersion.current().isJava11Compatible()) {
opt.addBooleanOption("-no-module-directories", true)
}
}
}
}
}
}
subprojects {
javadoc {
destinationDir = file("$rootDir/docs/")
configureJavadoc(it)
}
}
I was able to do it with:
def exportedProjects = [
":",
":module-a",
":module-b",
":module-c"
]
task allJavadoc(type: Javadoc) {
source exportedProjects.collect { project(it).sourceSets.main.allJava }
classpath = files(exportedProjects.collect { project(it).sourceSets.main.compileClasspath })
destinationDir = file("${buildDir}/docs/javadoc-all")
}
I'd love to filter specific java resources in my gradle project. Where some files should have replaced contents only, some should be also renamed (and have different content replaced).
My gradle java project setup is:
> cat build.gradle
apply plugin: 'java'
sourceSets {
main {
java {
resources {
srcDirs = [ "foo" ]
include '**/**'
}
}
}
}
processResources {
include '**/file_a.txt'
filter { String line ->
line
.replace("foo", "fool" )
}
}
processResources {
include '**/file_b.txt'
rename { "file_c.txt" }
filter { String line ->
line
.replace("ipsum", "zzz" )
}
}
> cat foo/file_a.txt
my name is foo
test ipsum
> cat foo/file_b.txt
lorem ipsum ...
Once running:
gradle build
I get:
> ls build/resources/main
file_c.txt
> cat build/resources/main/file_c.txt
my name is fool
test zzz
However I'd like to get both files, where only file_b.txt would be renamed and both would be replaced by the specific rules. What is the proper way to achieve that?
OK, found the solution myself, following seems to be working as expected:
apply plugin: 'java'
sourceSets {
main {
java {
resources {
srcDirs = [ "foo" ]
include '**/**'
exclude '**/*.txt'
}
}
}
}
processResources {
with copySpec {
from 'foo/file_a.txt'
filter { String line ->
line
.replace("foo", "fool" )
}
}
with copySpec {
from 'foo/file_b.txt'
rename { "file_c.txt" }
filter { String line ->
line
.replace("ipsum", "zzz" )
}
}
}
I, personally, think that resources and filtered resources should be kept separate. Ie src/main/resources and src/main/filteredResources. I also thing you should avoid excludes (eg exclude '**/*.txt') resources and filteredResources directories should contain ONLY what will end up in the jar... NOTHING ELSE
import org.apache.tools.ant.filters.ReplaceTokens
processResources {
with copySpec {
from 'src/main/filteredResources'
filter(ReplaceTokens, tokens: [foo: 'fool', ipsum: 'zzz'])
}
}
The above snippet will replace #foo# and #ipsum# in ALL files in the src/main/filteredResources folder
I am trying to add a native prebuilt shared library to my project in Android Studio. I am using the gradle-experimental:0.6.0-alpha5. However, whenever I try to add the prebuilt shared library to my application model, I get the following error:
Error:Cause:
org.gradle.api.internal.PolymorphicDomainObjectContainerConfigureDelegate
The library is added into the application model how it is described by the Google Gradle Experimental Guide:
repositories {
prebuilt(PrebuiltLibraries) {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("/path_to_libs/${targetPlatform.getName()}/shared_lib.so")
}
}
}
android.sources {
main {
jniLibs {
dependencies {
library "shared_lib"
}
}
}
}
The crucial line is library "shared_lib". There is no error if I uncomment this line.
Since this is not working, I have also tried to use the guide from ph0b.com. They are using a different syntax for adding native shared libraries (I just left out the headers since I do not have a single directory including all headers):
repositories {
libs(PrebuiltLibraries) {
shared_lib {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("/path_to_libs/${targetPlatform.getName()}/shared_lib.so")
}
}
}
}
android.sources {
main {
jni {
dependencies {
library "shared_lib" linkage "shared"
}
}
}
}
Nevertheless, this does not work as well. Android Studio does not copy my shared_lib to the apk file. Hence, I always get the following error:
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader [...] couldn't find "shared_lib.so"
Can anyone tell me how I can include native prebuild library into my project? I am using buildToolsVersion = '22.0.1' and compileSdkVersion = 22 as build parameters.
This one worked for me (0.6.0-beta6).
repositories {
prebuilt(PrebuiltLibraries) {
YourLib {
binaries.withType(SharedLibraryBinary) {
sharedLibraryFile = file("src/main/libs/armeabi-v7a/libYourLib.so")
}
}
}
}
android.sources {
main {
jniLibs {
dependencies {
library "YourLib"
}
}
}
}
Looks like they just forgot to mention the "YourLib {}" part around "binaries.withType".
Here's my first attempt at a C program built with Gradle's C plugin:
apply plugin: 'c'
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
}
}
}
This produces an executable called derpus.exe. I would like, if at all possible, to version these executables (derpus-1.0.0.exe, derpus-1.0.1.exe, etc.). When I change the derpus closure to derpus-1.0.0 like so:
derpus-1.0.0(NativeExecutableSpec) {
And run gradle clean build I get:
D:\workspace\derp\20150505\derpus>gradlew clean build
FAILURE: Build failed with an exception.
* Where:
Build file 'D:\derpus\build.gradle' line: 6
* What went wrong:
Could not compile build file 'D:\derpus\build.gradle'.
> startup failed:
build file 'D:\derpus\build.gradle': 6: unexpected tok
en: 0 # line 6, column 20.
derpus-1.0.0(NativeExecutableSpec) {
^
1 error
Does anybody know of a way to version these executables?
Update
Now this is really weird! Taking Amnon's advice, I added a gradle.properties file that defined version=1.0.0. I then modified my model closure to:
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
baseName = "derpus-${version}"
}
}
}
This produces an executable named derpus-1 (what?!?!)!
So then I modified model again:
version = "3.4"
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
baseName = "derpus-${version}"
}
}
}
As you can see, this should overrdide the version set in gradle.properties, however after running gradle clean build, it produces derpus-3!
So I modified model yet again:
model {
components {
derpus(NativeExecutableSpec) {
sources {
c(CSourceSet) {
source {
srcDir "src/derpus/c"
include "**/*.c"
}
exportedHeaders {
srcDir "src/derpus/headers"
}
}
}
baseName = "derpus-3.4.5"
}
}
}
This produces derpus-3.4!!! What is going on here?!? Does the C plugin have a bug in it that doesn't honor the full version variable?
In your example above the problem with derpus-1.0.0 is the gradle things that the dash character is a minus which is unexpected in a component spec name, thus the failure. You can overcome this by wrapping derpus-1.0.0 with inverted commas. A better approach, however, would be to apply the version to the baseName property of the component spec, i.e. add the following line under derpus component definition:
baseName = "derpus-1.0.0"
or
baseName = "derpus-$version"
Where in the second case the version property $version is taken from the project object.
Update
Per smeeb comments below another workaround that can be applied is to directly rename the target binaries:
afterEvaluate {
RenameNativeBinaries()
}
def RenameNativeBinaries() {
binaries.all { b ->
if (b instanceof SharedLibraryBinarySpec) {
b.sharedLibraryFile = ReconstructFileName(b.sharedLibraryFile)
} else if (b instanceof StaticLibraryBinarySpec) {
b.staticLibraryFile = ReconstructFileName(b.staticLibraryFile)
}
}
}
def ReconstructFileName(File originalFile) {
def originalFileName = originalFile.absolutePath
def filePath = FilenameUtils.getFullPath(originalFileName)
def baseName = FilenameUtils.getBaseName(originalFileName)
def extension = FilenameUtils.getExtension(originalFileName)
def newName = "$baseName-$version.$extension"
def newFile = new File(filePath, newName)
newFile
}
Where FilenameUtils is taken from commons-io:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath group: 'commons-io', name: 'commons-io', version: '2.4'
}
}