Gradle: How to make a compile scope file dependency excluded in packaging? - build

I have a multi-module gradle project with the following basic structure:
root
core
c-interface
m-interface
The c-interface and m-interface both depend on the core project:
compile project(':root:core')
c-interface and m-interface use the WAR plugin, but core does not and is just a jar.
In the core project, I am pulling in some file system dependencies with the following. One of these dependencies I cannot have packaged in the WARs generated by c-interface and m-interface. Previously I had this dependency in a nexus maven repository so I could exclude it by group,name,version in a providedRuntime configuration in c-interface and m-interface.
I cannot figure out how to do the same for the file dependency. The gradle dependencies task does not list file dependencies so I don't know what I would put in a providedRuntime.
I read http://issues.gradle.org/browse/GRADLE-471 but trying to use the idea there doesn't seem to remove the archive from my packages. Here is what I am currently defining (in core's build.gradle):
compile fileTree(dir: 'dependencies/compile/archive', include: '*.jar', exclude: 'management.jar')
compile(files('dependencies/compile/archive/management.jar')){ notPackaged = true } // Excludes it from all publications
Update
providedCompile without war plugin looked like a possibility. I set this up in the core build.gradle and it compiled fine, but c-interface and m-interface also needed the dependency at compile time. Including the file as providedCompile (or even a sanity check with compile) in c-interface and m-interface did not fix compile time errors related to missing the management.jar dependency. My speculation is because it was already scoped as providedCompile in core that the new declarations are ignored in c-interface and m-interface.
core/build.gradle:
configurations { providedCompile }
dependencies {
providedCompile files('dependencies/compile/archive/management.jar')
}
sourceSets.main.compileClasspath += configurations.providedCompile
sourceSets.test.compileClasspath += configurations.providedCompile
sourceSets.test.runtimeClasspath += configurations.providedCompile
c-interface/build.gradle:
providedCompile files('dependencies/compile/archive/management.jar')

There probably is a cleaner and simpler solution but you could then specify a custom configuration:
configurations {
compileOnly
}
and then specify all dependencies:
dependencies {
compile fileTree(dir: 'dependencies/compile/archive', include: '*.jar', exclude: 'management.jar')
compileOnly files('dependencies/compile/archive/management.jar')
}
Finally add the compileOnly configuration to classpaths of all source sets
sourceSets.all {
compileClasspath += configurations.compileOnly
}
This way management.jar should be on the classpath for compilation but won't be packaged.
EDIT
Only now I fully understand your problem. The following worked for me on a test project.
In core project gradle file:
repositories {
flatDir {
dirs 'dependencies/compile/archive'
}
}
dependencies {
compile fileTree(dir: 'dependencies/compile/archive', include: '*.jar', exclude: 'management.jar')
compile ':management:'
}
In project that depends on core:
repositories {
flatDir {
dirs new File(project(':core').projectDir, 'dependencies/compile/archive')
}
}
dependencies {
compile(project(':core')) {
exclude module: 'management'
}
compileOnly ':management':
}
sourceSets.all {
compileClasspath += configurations.compileOnly
}

Related

Some problems were found with the configuration of task ':app:generateDebugApolloIR' (type 'ApolloIRGenTask')

I've updated my gradle version to latest version and now my project is not able to build. The following errors are being shown on logcat while building project.
FAILURE: Build failed with an exception.
* What went wrong:
Some problems were found with the configuration of task ':app:generateDebugApolloIR' (type 'ApolloIRGenTask').
- In plugin 'com.amazonaws.appsync' type 'com.apollographql.apollo.gradle.ApolloIRGenTask' field 'extension' without corresponding getter has been annotated with #Internal.
Reason: Annotations on fields are only used if there's a corresponding getter for the field.
I've tried to rebuild project, clean project, invalidate caches. But still having the same issue.
My build.gradle Project Level:
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.google.gms:google-services:4.3.14'
classpath 'com.google.ar.sceneform:plugin:1.17.1'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10'
classpath 'com.amplifyframework:amplify-tools-gradle-plugin:1.0.1'
classpath "com.amazonaws:aws-android-sdk-appsync-gradle-plugin:3.1.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
build.gradle app level
//AWS
implementation 'com.amplifyframework:core:1.29.0' //updated
implementation 'com.amplifyframework:aws-api:1.28.3' //updated
implementation 'com.amplifyframework:aws-datastore:1.28.3' //updated
implementation 'com.amazonaws:aws-android-sdk-appsync:3.1.1' //updated
implementation 'com.amazonaws:aws-android-sdk-s3:2.35.0' //updated
Upgrade your library versions
build gradle project level
dependencies {
classpath 'com.android.tools.build:gradle:7.3.1'
classpath 'com.google.gms:google-services:4.3.14'
classpath 'com.google.ar.sceneform:plugin:1.17.1'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10'
classpath 'com.amplifyframework:amplify-tools-gradle-plugin:1.0.1'
classpath "com.amazonaws:aws-android-sdk-appsync-gradle-plugin:3.3.0"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
build gradle app level
//AWS
implementation 'com.amplifyframework:core:1.31.3' //updated 1.31.3
implementation 'com.amplifyframework:aws-api:1.28.3' //updated
implementation 'com.amplifyframework:aws-datastore:1.28.3' //updated
implementation 'com.amazonaws:aws-android-sdk-appsync:3.3.0' //updated 3.3.0
implementation 'com.amazonaws:aws-android-sdk-s3:2.40.0' //updated 2.40.0
build project now, it will work

Is there a way to make NativeLibrarySpec a part of task in gradle build file

I am trying to generate shared and static libraries in C++ project through gradle. Following is my build.gradle file.
apply plugin : 'cpp'
model{
components {
els(NativeLibrarySpec){
sources {
cpp {
source {
srcDirs "src/grad"
include "**/*.cpp", "**/*.h"
}
}
}
}
}
}
Here libraries are generated as soon as gradle build command is run. I don't want to run from build. I want to make it as a specific task so that, only when I call that task, libraries are generated.
I tried something like this
task libsGen(){
model{
components {
els(NativeLibrarySpec){
sources {
cpp {
source {
srcDirs "src/grad"
include "**/*.cpp", "**/*.h"
}
}
}
}
}
}
}
But here also as soon as gradle build command is run, libraries are generated. I want libraries to be generated only when I run task libsGen() explicitly.
I'm using Gradle 7.4.2 version.
Please help, I'm new to c++ and gradle.

Error "/usr/bin/ld: cannot find library: File format not recognized" when application is built as part of a collection of products

I have a QBS Project which is a collection of subprojects, including static libraries, shared libraries, and a Qt GUI applications. The Qt GUI application has been giving me issue in that the linking stage fails, throwing several "/usr/bin/ld: cannot find {library}: File format not recognized" errors for libraries that are built earlier in the project chain. It does not do this for all libraries though, including libraries with near identical .qbs files as those which do throw this error.
Oddly enough, if I build the application on it's own, that is to say I run qbs from within the application's project directory rather than at the top level, it builds fine (assuming the dependent libraries all exist within their install directories). The main difference I see is that when building the full project, the cpp.libraryPaths for the application are ignored for all products in the project and the application attempts to link against the lib files produced in the build directory, while when building the application on it's own the cpp.libraryPaths are used as intended, and the files in the install directory are linked against successfully.
I have no idea why the lib files in the install directory can be linked against while files in the build directory throw errors. What could be causing the linking to fail in the first place? Additionally, how can I fix my project configuration so that I can build everything by calling qbs at the top level. Am I perhaps going about this in the wrong manner?
Here is the command I use to start the build:
qbs qbs.installRoot:. release
And a visual representation of the issue:
Poject <-- calling qbs here throws errors at linking application
|- LibraryOne
|- LibraryTwo
|- Application <-- calling qbs here works if libraries already built
And here is a very simplified reproduction of the relevent qbs files
-- SubOne.qbs and SubTwo --
// These are identical excluding the files
StaticLibrary {
name: // "One" or "Two"
files: [/*Files...*/]
Depends {
name: "Qt"
submodules: [/*core, etc...*/]
}
Depends { name: "cpp" }
// cpp depends and properties
Group {
fileTagsFilter: product.type
qbs.installDir: "lib"
qbs.install: true
}
}
-- App.qbs --
QtGuiApplication {
name: "App"
files: [/*Files...*/]
Depends { name: "One" } // I comment out these depends when building the Application on it's own
Depends { name: "Two" }
Depends { name: "cpp" }
cpp.includePaths: ["../One/include","..Two/include"]
cpp.libraryPaths: ["../lib"] // <-- Ignored during full project build
cpp.staticLibraries: ["One","Two"]
Group {
fileTagsFilter: product.type
qbs.installDir: "bin"
qbs.install: true
}
}
Never run qbs from a subdirectory. You should always run it on the top-level project file. In your root directory you should have a file like this:
// project.qbs
import qbs
Project {
// order doesn't matter here
references: [
"LibraryOne/SubOne.qbs",
"LibraryTwo/SubTwo.qbs",
"Application/App.qbs"
]
}
Secondly, you should not set the cpp.libraryPaths and cpp.staticLibraries in your application, as the Depends items which you have in your application, will already handle this (never comment them out).
Your cpp.includePaths properties should also not be set in the application, instead they should go into an Export item in each of your respective static libraries, like so:
StaticLibrary {
...
Export {
Depends { name: "cpp" }
cpp.includePaths: [product.sourceDirectory + "/include"]
}
...
}
Then run qbs -f project.qbs and everything should be built correctly.

Gluon build as single Jar

I'd like to build my Gluon Project as a SINGLE executable jar file.
Currently there is a startup script included with a bin folder and so on.
Is it possible to build a single jar? Or can I include an own gradle task that accomplishes this?
The current tasks like installApp or distZip will not bundle the jars in one.
If you want to create a 'fat-jar', you can add this plugin to your build.gradle script:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.8'
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.3'
}
}
apply plugin: 'org.javafxports.jfxmobile'
apply plugin: 'com.github.johnrengelman.shadow'
And then run gradlew shadowJar. It will create under libs an executable jar.
Note: if you are using desktopCompile or desktopRuntime dependencies, those won't be included so you need to change those to compile or runtime.
Since I had to build the jar with javapackager I used this plugin: javafx-gradle-plugin
I am relatively new to Gradle so adding the dependencies is just a temporary solution but it works
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'org.javafxports:jfxmobile-plugin:1.0.8'
classpath group: 'de.dynamicfiles.projects.gradle.plugins', name: 'javafx-gradle-plugin', version: '8.4.1'
}
}
jfx {
verbose = true
mainClass = "package.path.to.main.class.MainClass"
jfxAppOutputDir = "build/jfx/app" //configurable
jfxMainAppJarName = "ProjectName.jar"
deployDir = "src/main/deploy" //for signing
//many more options, go to link to learn about them
}
jfxJar.doFirst {
//TODO add all desktop dependencies
println("adding desktop dependency")
project.dependencies.add("runtime", "com.gluonhq:charm-desktop:2.1.0")
}

Why doesn't Gradle include transitive dependencies in compile / runtime classpath?

I'm learning how Gradle works, and I can't understand how it resolves a project transitive dependencies.
For now, I have two projects :
projectA : which has a couple of dependencies on external libraries
projectB : which has only one dependency on projectA
No matter how I try, when I build projectB, gradle doesn't include any projectA dependencies (X and Y) in projectB's compile or runtime classpath. I've only managed to make it work by including projectA's dependencies in projectB's build script, which, in my opinion does not make any sense. These dependencies should be automatically attached to projectB. I'm pretty sure I'm missing something but I can't figure out what.
I've read about "lib dependencies", but it seems to apply only to local projects like described here, not on external dependencies.
Here is the build.gradle I use in the root project (the one that contains both projectA and projectB) :
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:0.3'
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'idea'
group = 'com.company'
repositories {
mavenCentral()
add(new org.apache.ivy.plugins.resolver.SshResolver()) {
name = 'customRepo'
addIvyPattern "ssh://.../repository/[organization]/[module]/[revision]/[module].xml"
addArtifactPattern "ssh://.../[organization]/[module]/[revision]/[module](-[classifier]).[ext]"
}
}
sourceSets {
main {
java {
srcDir 'src/'
}
}
}
idea.module { downloadSources = true }
// task that create sources jar
task sourceJar(type: Jar) {
from sourceSets.main.java
classifier 'sources'
}
// Publishing configuration
uploadArchives {
repositories {
add project.repositories.customRepo
}
}
artifacts {
archives(sourceJar) {
name "$name-sources"
type 'source'
builtBy sourceJar
}
}
}
This one concerns projectA only :
version = '1.0'
dependencies {
compile 'com.company:X:1.0'
compile 'com.company:B:1.0'
}
And this is the one used by projectB :
version = '1.0'
dependencies {
compile ('com.company:projectA:1.0') {
transitive = true
}
}
Thank you in advance for any help, and please, apologize me for my bad English.
I know that this specific version of the question has already been solved, but my searching brought me here and I hope I can save some people the hassle of figuring this out.
Bad foo/build.gradle
dependencies {
implementation 'com.example:widget:1.0.0'
}
Good foo/build.gradle
dependencies {
api 'com.example:widget:1.0.0'
}
bar/build.gradle
dependencies {
implementation project(path: ':foo')
}
implementation hides the widget dependency.
api makes the widget dependency transitive.
From https://stackoverflow.com/a/44493379/68086:
From the Gradle documentation:
dependencies {
api 'commons-httpclient:commons-httpclient:3.1'
implementation 'org.apache.commons:commons-lang3:3.5'
}
Dependencies appearing in the api configurations will be
transitively exposed to consumers of the library, and as such will
appear on the compile classpath of consumers.
Dependencies found in the implementation configuration will, on the
other hand, not be exposed to consumers, and therefore not leak into
the consumers' compile classpath. This comes with several benefits:
dependencies do not leak into the compile classpath of consumers anymore, so you will never accidentally depend on a transitive
dependency
faster compilation thanks to reduced classpath size
less recompilations when implementation dependencies change: consumers would not need to be recompiled
cleaner publishing: when used in conjunction with the new maven-publish plugin, Java libraries produce POM files that
distinguish exactly between what is required to compile against the
library and what is required to use the library at runtime (in other
words, don't mix what is needed to compile the library itself and what
is needed to compile against the library).
The compile configuration still exists, but should not be used as it will not offer the guarantees that the api and implementation
configurations provide.
Finally, the problem didn't come from the scripts. I've just cleared gradle's cache, and each project's build folder, to make this work.
Put the following line in projectB's dependencies.
compile project(':projectA')