Get build.gradle file as a .class file - java

I have a gradle file which prints "Hello World"
task hello << {
println "Hello World"
}
This script is written in groovy. As I know we can get the output of Test.groovy into Test.class as it uses JVM. So my question is how to get the .class file of build.gradle file? Is there any specific command which I need to provide to the gradle demon?

It's true that Gradle scripts (build.gradle, init script or settings script) will be compiled into Java bytecode, during the Gradle build initialization phase. The result .class files are generated by Gradle into internal "script" cache directory structure under ${user.home}/.gradle/caches/${gradle.version}/scripts.
But this compilation process is something internal to Gradle implementation, it's not exposed through the DSL or from API (as far as I know): you can find some implementation details in the core submodule from Gradle source code : see internal package https://github.com/gradle/gradle/tree/master/subprojects/core/src/main/java/org/gradle/groovy/scripts
I don't think you can access these .class files programatically, even by hacking Gradle core implementation, but as others said in comments: why would you need that??

Related

Running an uber jar from sbt assembly results in error: Could not find or load main class

I have a spark job packaged as an uber-jar using the sbt assembly plugin.
The build.sbt specifies a runnable main to be the target of the resulting uber-jar
mainClass in assembly := Some("com.foo.Bar")
After the assembly is correctly created, running the intended command:
java -jar assembly.jar
results in
Error: Could not find or load main class com.foo.Bar
Using the an alternative method, like java -cp assembly.jar com.foo.Bar gives the same error message.
Then, I extracted the contents of the uber-jar in a new directory. I can see my com/foo/ directory and the Bar.class file.
From the root of the extracted directory I tried:
java -cp . com.foo.Bar
and I get a correct result.
Further trying to find the reason of the error, I tried:
java -verbose -jar assembly.jar
I can see the java core classes being loaded, but I don't see any of my packaged classes being loaded.
What can possibly be wrong here?
After an extensive investigation (read: pulling hairs out), it turns out that this behavior is the result of a rogue INDEX.LIST from one of the flattened jar files landing in the META-INF directory of the resulting uber-jar.
Following the JAR file spec, the INDEX.LIST, if present, dictates what packages from the Jar file are to be loaded.
To avoid this, we updated the mergeStrategy with a rule to avoid any pollution of the resulting META-INF directory:
case PathList("META-INF", xs # _*) => MergeStrategy.discard
This fixed the issue and returned my sanity.
Update:
After some extra searching, it turns out that the default merge strategy takes proper care of INDEX.LIST. This answer applies when the customized merge strategy contains cases that handle the META-INF pathSpec

Maven project execution command

Below is my sample class file:
package org.foo.tutorial;
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
In order to execute the project (maven framework) we run:
>java -cp Something-1.0.SNAPSHOT.jar org.foo.tutorial.APP
The above command works fine and gives me the output 'HELLO WORLD'.
However, if I leave out the third argument in the above command (org.foo.tutorial.APP) I get the following error:
Error: Could not find or load main class target.MavenTutorialApp-1.0-SNAPSHOT.jar
My question is:
Why should the groupId and app name matter when I am supplying the entire 'jar' file ?
The error is a bit misleading. Your java command is incorrect since you don't specify a class. The Something-1.0.SNAPSHOT.jar is meant to be part of the -cp option but java is interpreting it as the class.
That's how java behaves
The java command starts a Java application. It does this by starting a
Java runtime environment, loading a specified class, and calling that
class's main method.
If your .jar file contains an entry point specified by a Main-Class header in the manifest, then you can simply run
java -jar Something-1.0.SNAPSHOT.jar
Let me try to answer your question.
Why should the groupId and app name matter when I am supplying the
entire 'jar' file ?
Lets divide the question into smaller part -
What is group id? - The id of the project's group.
What is artifactId? - The id of the artifact (project) and off course version is part of default artifact name.
While running a java program under jvm there are no such effect that how you built jar, for example it is produced by maven or gradle build process or even command line.
Things that matter is jar file and entry point or the class where main reside.
This may be out of scope of this question, but i felt relevant.
To run java program from jar file, you can explicitly mention like above. Also you can create executable jar file by adding manifest file, where it define the entry point of the executable -
Main-Class: org.foo.tutorial.APP
How to create executable jar?
Also maven maven-assembly-plugin helps to package executable jar.
help

j2objc Xcode build rules, not recognizing imports

I am using j2objc to compile and use a java library in iOS. I followed the processes:
http://j2objc.org/docs/Xcode-Build-Rules.html
http://j2objc.org/docs/Required-Link-Flags.html
I do not get any build errors until I start importing the header files to use them:
#import "org/library/Class.h"
The files are not found. What I am missing?
On the other hand, I tried to use the manually translated library files (using the terminal j2objc commands). If I pùt the .h and .m files into the j2objc-dist/include folder they are recognized by the editor and I can use the classes without compile errors. But, when I try to build the project it finds errors of the type _OBJ_CLASS_$_Java. I tried to include the files to the compile list in Xcode and I verified the path of libjre_emul.a but I still get the error.
My library contains packages so it has multiple folders in a tree.
My preference will be to use the first method (original Java sources)
DATA FOR JAVA SOURCES CASE:
Build rules:
Java source files
Custom script:
/Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/j2objc -d ${DERIVED_FILES_DIR} -sourcepath ${PROJECT_DIR}/src/ ** \ --no-package-directories ${INPUT_FILE_PATH};
Output files:
${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.h
${DERIVED_FILES_DIR}/${INPUT_FILE_BASE}.m
Build phases
Link Binary with libraries:
libicucore.dylib
Security.framework
libz.dylib
Build Settings
Linking - Other Linker Flags:
-ljre_emul -L /Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/lib -force_load /Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/lib/libjre_emul.a -l jre_emul -ObjC
Search Paths - Library Seargh Paths:
/Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/lib
Search Paths - User Header Search Paths:
/Users/xgibert/Desktop/Orekit_iOS/j2objc-dist/include
My java library files are in Project_root/src. The tree looks like this:
root/
src/
org/
orekit/
data/
time/
...
apache/
...
In my ViewController.m file I try to import with the following line without success (file not found):
#import "org/orekit/data/DataProvidersManager.h"
Xcode assumes all sources are in a top-level directory, so imports such as you describe fail. As described in the Xcode-Build-Rules page, the --no-package-directories flag is needed, as it outputs all generated files to the specified build directory without sub-directories, and generates correct #import directives.
A sample project that demonstrates including Java sources with packages is j2objc-sample-reversi. Its UI sucks (I wrote it, sigh), but the game engine is decent; if you need a tougher opponent, crank up the engine strength here.

Running an executable jar file built from a gradle based project

I have a standalone project which is gradle based. When I do gradle build, the jar is generated under build/libs. How do I run this executable jar from command line? I tried : java -cp build/libs/foo.jar full.package.classname but I get noClassFoundException for the classes that were imported. How do I include dependent jars as part of classpath?
Since question is marked with gradle tag I assume you want to run jar from gradle build. I also assume you use java plugin for your gradle build.
Add next lines in your gradle:
task runFinalJar(type: JavaExec) {
classpath = files('build/libs/foo.jar')
classpath += sourceSets.main.runtimeClasspath
main = full.package.classname
}
You can now include your task to the build process:
build.dependsOn.add("runFinalJar")
Or just run it form command line:
gradle build runFinalJar
UPDATE: It is cleaner to use application plugin as Peter suggested
Add a simple task to run jar
task runJar(type: JavaExec) {
main = "-jar";
args jar.archivePath
}
UPDATE: jar.archivePath is now deprecated, you can use jar.archiveFile.get()
task runJar(type: JavaExec) {
main = "-jar";
args jar.archiveFile.get()
}
Either use the application plugin to create an archive containing your code, its dependencies, and startup scripts, or create an executable fat Jar. The latter shouldn't be done in the naive way, but with the gradle-one-jar (or a similar) plugin.
I think that the answers go beyond what the question actually is. The question is, or can be restated as, how to run a JAR which gradle builds.
The questioner states that they've tried java -cp build/libs/foo.jar full.package.classname to no avail.
The correct syntax is java -jar build/libs/foo.jar, or if the JAR is right there, obviously it's then just java -jar foo.jar as normally.
The question should be edited for clarity, IMHO.
I am a newbie, so my explanations here will be simplistic. My build.gradle file contains only one line: apply plugin: 'java'. I have a hello world java code in src/main/java/org/dx/test/App.java. From the command shell, I typed: gradle build. And then I saw this jar file magically created:
build/libs/helloworld.jar
All of the above answers did not work. What worked for me is:
java -cp build/libs/helloworld.jar org.dx.test.App
Now, I know gradle is full of sorcercy so I am sure my situation may not fully reflect your situation. The actions are did were:
Create that one line build.gradle file
Create the App.java under the doctor's prescribed folder location
Type gradle build
To run a jar in terminal, first build a jar using "gradle clean build" then , navigate to -> build -> distribution -> unzip <filename>.zip file
-> cd to unzipped file
-> cd bin
there will be 2 files - projectname & <projectname.bat> run the jar with ./projectname
If there are some args to be passed to main method use : run the jar with ./projectname params

How do you configure cmake to only rebuild changed .java files in a java project?

I have a cmake project that looks like:
project(myProject JAVA)
add_library(myLibrary foo.java bar.java)
but when I run make in the directory, all the java files are rebuilt, even if they weren't changed. Is there a way to turn off that behavior?
Thanks,
The add_library Java support in CMake is not too hot. It ignores the "package" directive, and assume that "foo.java" creates "foo.class" in the base directory, not in a sub-directory com/example/ for package com.example;.
If you look at the generated makefiles in CMakeFiles/<jar_file>.dir/build.make, it has code like this (cleaned up a bit)
CMakeFiles/test.dir/foo.class: ../foo.java
javac $(Java_FLAGS) /full/path/to/foo.java -d CMakeFiles/test.dir
This is a broken dependency when foo.java contains "package com.example;" at the top. Make expects foo.class to be created, when it isn't and you run make again, it will compile foo.java to see if maybe this time it will work. The actual file generated is in com/example (which luckily gets added to the final jar file).
The good news is that things have improved recently. In version 2.8.6 of CMake a new module was added called UseJava that does a much better job of compiling Java files and correctly rebuilding when there are changes. Instead of using add_library you need to use add_jar. Here is a complete example CMakeLists.txt file:
cmake_minimum_required(VERSION 2.8.6)
find_package(Java)
include(UseJava)
project(java_test Java)
set(SRC
src/com/example/test/Hello.java
src/com/example/test/Message.java
)
add_jar(hello ${SRC})
That will produce hello.jar from the input source files.
I think your answer is to just build the entire Java project. If you change one class and just recompile it, how will cmake know to compile another class that depended on it. What happens if you remove a method in one class that others depend on, skipping recompiling the other classes will give you run-time errors instead of a compiler error.
However, 40 java files is a small amount and it seems like they should compile in seconds or less.

Categories

Resources