I have a gradle multi-project environment structured like this:
- root
- a
- b
- c
- utils
root's settings.gradle file is mostly this:
include ':a', ':b', ':c', ':utils'
a, b, c have a dependency on utils.
I'm using intellij-idea as IDE. The problem is that on the gradle view the structure it shows is
- root
- :utils
- root
- a
- :a (root)
- :b
- :c
- :utils
- :root
... //the same for b, c and utils
I'm not sure this is a real issue itself, but I suppose that it might cause some slowness in project building.
Moreover, there's another issue that is more troubling: in every subproject's module's build.gradle file I'm using a function that I've defined in root's build.gradle. This function adds a task. The problem is that the task is added to every node root child of a,b,c or utils but not to the root root node.
//hypothetical extract from a's build.gradle
...
task addTask {
foo(project, ['param1','param2'])
}
//root's build.gradle
ext.foo = { Project prj, List<String> params ->
params.each {
p -> task "addedTask-${p}"() {
println 'hello'
}
}
}
I suppose that there is a heavy configuration problem in my project's configuration but I really don't know where to start looking for it.
Related
Following the setup described in Simple sharing of artifacts between projects, we are in the special case where we have a multi module gradle build that produce different types of jars and we would like to declare a dependency to those jar in a configuration.
dependencies {
instrumentedClasspath(project(path: ":producer", configuration: 'instrumentedJars'))
}
from the docs works great.
In the project dependency-tests I have a project that reproduce the setup (with different names, but the idea is the same).
But I am doing this in a Gradle-plugin and I would like to have the same declaration in java.
DependencyHandler dependencyHandler = project.getDependencies();
// this adds a dependency to the main jar of the 'producer' project:
dependencyHandler.add("instrumentedClasspath", project.getRootProject().findProject(":producer"));
// this is not working:
dependencyHandler.add("instrumentedClasspath", project.getRootProject().findProject(":producer").getConfigurations().getByName("instrumentedJars"));
Failing with:
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':printConf'.
> Could not resolve all dependencies for configuration ':instrumentedJars'.
> Cannot convert the provided notation to an object of type Dependency: configuration ':producer:instrumentedJars' artifacts.
The following types/formats are supported:
- Instances of Dependency.
- String or CharSequence values, for example 'org.gradle:gradle-core:1.0'.
- Maps, for example [group: 'org.gradle', name: 'gradle-core', version: '1.0'].
- FileCollections, for example files('some.jar', 'someOther.jar').
- Projects, for example project(':some:project:path').
- ClassPathNotation, for example gradleApi().
Comprehensive documentation on dependency notations is available in DSL reference for DependencyHandler type.
* Try:
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
project(...)
inside the dependencies block comes from the DependencyHandler, and
path: ":producer", configuration: 'instrumentedJars'
is actually a map {"path"=":producer", "configuration"="instrumentedJars"}.
So something like that should work in Java:
Map<String, String> map = new HashMap<>();
map.put("path", ":producer");
map.put("configuration", "instrumentedJars");
dependencyHandler.add("instrumentedClasspath", dependencyHandler.project(map));
Note: When using Kotlin build script you can easily see types and declarations of functions and might be easier for discovering API. So in Kotlin project(...) in the dependencies block is an extension method defined as:
fun DependencyHandler.project(
path: String,
configuration: String? = null
): ProjectDependency =
uncheckedCast(
project(
if (configuration != null) mapOf("path" to path, "configuration" to configuration)
else mapOf("path" to path)
)
)
In my Skylark rule, I am looking through all my deps - some of them are maven_jar instances defined in my WORKSPACE file. For those, I would like to access the value of maven_jar.artifact, but as far as I can tell it isn't available. Is it possible to get at that value?
For example, if my WORKSPACE has:
maven_jar(
name = "com_google_guava_guava",
artifact = "com.google.guava:guava:20.0",
)
And my BUILD file has something like this:
my_rule(
name = "foo",
deps = ["#com_google_guava_guava//jar"]
)
In the implementation of my_rule, I would like to get the value com.google.guava:guava:20.0.
I think you'll need to file a feature request for this:
https://github.com/bazelbuild/bazel/issues/new
The instance of the maven_jar rule in the workspace file isn't available to the rules in BUILD files, only the rules which the workspace rule generates are (i.e., #com_google_guava_guava//jar). Off the top of my head, maven_jar would have to generate a rule into the jar's workspace which has an attribute with the value of artifact, and that rule would need to create a provider containing that value for other rules to consume.
(There does happen to be META-INF/maven/com.google.guava/guava/pom.xml inside the jar, which seems to have the information you want, but I don't know if you can rely on that for all jars from maven, but either way, the contents of the jar aren't available at analysis time (within the rule implementation))
I have a problem with Scala code with Java methods.
It is calling:
value getDepth is not a member of amqpManagment.utils.data.ChessObject
var depth: Int = chessObjects.getDepth()
^
However i use getDepth in many other places in Java code and it works fine.
Also after put that code it was working in InteliJ by few hours which is weird but maybe project didnt rebuild itself after that change...
However InteliJ shows code is okay, but during compiling it shows that error. Rebuilding by InteliJ or terminal doesnt help.
Scala code:
import amqpManagment.utils.data.ChessObject
object ChessScheduler {
// DEPTH GAME
def startGameWithDepthRule(chessObject: ChessObject) : Integer =
{
...
val depth: Int = chessObjects.getDepth()
...
}
}
Java Code:
#Getter
#Setter
public class ChessObject {
private Integer depth;
...
}
build.sbt
import sbt.Keys._
import sbt.Level
name := "ChessEngineModuler"
logLevel := Level.Warn
version := "1.0"
scalaVersion := "2.12.2"
Thank you for your help.
Hello #Chenna Reddy :)
Thank you for your post, It seems it was problem with Lombok indeed. However after your answer i realised it was a problem because Scala code was compiled before Java one.
I check three solutions cause i had added dependency and Annotation Processor On.
First solution is just adding Getters and Setters to Java class not by the Lombok, however it is ugly solution
Second Solution is just adding in Files -> Settings -> Build, Execution, Deployment -> Compiler -> Scala Compiler -> Compile Order -> Java then Scala.
Third one is set in build.sbt -> compileOrder := CompileOrder.JavaThenScala
I think 3rd is the best one if we want deploy that code somewhere :)
Looks like you are using lombok for auto generation of getters. Please add lombok dependency.
libraryDependencies += "org.projectlombok" % "lombok" % "1.16.16"
Above step is not required if you are building Java project seperately and that project has lombok as a compile time dependency. Then generated jar file must have all the getters already.
Regarding why Intellij shows error sometimes, its possible that you didn't enable annotation processing from Files -> Settings -> Build, Execution, Deployment -> Compiler -> Annotation Processors.
In Gradle you need to define subprojects to be built in a 'settings.gradle' file. To build three child projects, you would do something like this:
include "child1", "child2", "child3"
The problem I'm having is that I have quite a few projects to include. Is there a way to use a wildcard in this definition? I'm looking for something like this:
include "*"
That of course does not work. This would be a lot easier to work with since I have many subprojects to include. Is there a way to automatically include subdirectories as projects?
include rootDir.listFiles().findAll {
it.isDirectory()
&& !( it =~ ".*/\\..*") // don't add directories starting with '.'
&& !( it =~ "^\\..*") // don't add directories starting with '.'
}.collect {
it.getName()
}.toArray(new java.lang.String[0])
Did the trick for me
The following code supports a project hierarchy of arbitrary depth:
rootDir.eachFileRecurse { f ->
if ( f.name == "build.gradle" ) {
String relativePath = f.parentFile.absolutePath - rootDir.absolutePath
String projectName = relativePath.replaceAll("[\\\\\\/]", ":")
include projectName
}
}
Can you do something like:
include (1..10).collect { "Child$it" }
To include "Child1" up to "Child10"?
Obviously, you'd need to change the collect to some sort of folder scan, but it that quick test works then the scan has a good chance
I have a java project that is built with buildr and that has some external dependencies:
repositories.remote << "http://www.ibiblio.org/maven2"
repositories.remote << "http://packages.example/"
define "myproject" do
compile.options.target = '1.5'
project.version = "1.0.0"
compile.with 'dependency:dependency-xy:jar:1.2.3'
compile.with 'dependency2:dependency2:jar:4.5.6'
package(:jar)
end
I want this to build a single standalone jar file that includes all these dependencies.
How do I do that?
(there's a logical followup question: How can I strip all the unused code from the included dependencies and only package the classes I actually use?)
This is what I'm doing right now. This uses autojar to pull only the necessary dependencies:
def add_dependencies(pkg)
tempfile = pkg.to_s.sub(/.jar$/, "-without-dependencies.jar")
mv pkg.to_s, tempfile
dependencies = compile.dependencies.map { |d| "-c #{d}"}.join(" ")
sh "java -jar tools/autojar.jar -baev -o #{pkg} #{dependencies} #{tempfile}"
end
and later:
package(:jar)
package(:jar).enhance { |pkg| pkg.enhance { |pkg| add_dependencies(pkg) }}
(caveat: I know little about buildr, this could be totally the wrong approach. It works for me, though)
I'm also learning Buildr and currently I'm packing Scala runtime with my application this way:
package(:jar).with(:manifest => _('src/MANIFEST.MF')).exclude('.scala-deps')
.merge('/var/local/scala/lib/scala-library.jar')
No idea if this is inferior to autojar (comments are welcome), but seems to work with a simple example. Takes 4.5 minutes to package that scala-library.jar thought.
I'm going to use Cascading for my example:
cascading_dev_jars = Dir[_("#{ENV["CASCADING_HOME"]}/build/cascading-{core,xml}-*.jar")]
#...
package(:jar).include cascading_dev_jars, :path => "lib"
Here is how I create an Uberjar with Buildr, this customization of what is put into the Jar and how the Manifest is created:
assembly_dir = 'target/assembly'
main_class = 'com.something.something.Blah'
artifacts = compile.dependencies
artifacts.each do |artifact|
Unzip.new( _(assembly_dir) => artifact ).extract
end
# remove dirs from assembly that should not be in uberjar
FileUtils.rm_rf( "#{_(assembly_dir)}/example/package" )
FileUtils.rm_rf( "#{_(assembly_dir)}/example/dir" )
# create manifest file
File.open( _("#{assembly_dir}/META-INF/MANIFEST.MF"), 'w') do |f|
f.write("Implementation-Title: Uberjar Example\n")
f.write("Implementation-Version: #{project_version}\n")
f.write("Main-Class: #{main_class}\n")
f.write("Created-By: Buildr\n")
end
present_dir = Dir.pwd
Dir.chdir _(assembly_dir)
puts "Creating #{_("target/#{project.name}-#{project.version}.jar")}"
`jar -cfm #{_("target/#{project.name}-#{project.version}.jar")} #{_(assembly_dir)}/META-INF/MANIFEST.MF .`
Dir.chdir present_dir
There is also a version that supports Spring, by concatenating all the spring.schemas