TL;DR: Is there a standard way in the Java world, to have the build tools install the executables they just built (like the make install of the C world)?
(I would be happy with a solution that would work only on Linux)
More details:
I have a Java project distributed via github. Compilation and dependencies are managed with maven 2. Running mvn package builds a tarball with my jar and the dependencies needed at runtime, plus an executable script which set the classpath and launch the main jar:
#!/bin/bash
cpBase="$(dirname "$0")"
java -cp "$cpBase/*" dw.cli.Program $#
So, if someone wants to install this on her computer, one need to:
run mvn package
and then to unpack the tarball and to copy the content in a directory on her PATH.
On the other hand I like the way the autotools are working: the user doesn't need to copy anything manually, because the build step make install handles the installation for her.
I could emulate this behaviour using cp through ant tasks in my pom.xml, but I'm more interested in learning the Java good practices than to provide non standard behaviors.
It seems maven doesn't provide this behavior. On the other hand, I'm totally ignorant of what the other Java build tool can do wrt to this.
Edit:
As far as I understand mvn install and mvn deploy don't fit my need, because they will install my jar in my local or remote repository. Whereas I want to install my executables on my PATH (eg: to install my wrapper script in /usr/local/bin)
The question is tagged "gradle", so I'll supply the Gradle answer.
I take it you're building an application, not a library. In that case, Gradle is thoughtfully supplying the application plugin.
apply plugin: 'application'
The plugin will supply you the run, distZip, distTar and installDist tasks, which do just what they sound like. Check out the documentation at
the official web site.
Note that the installDist task doesn't, by default, put the software anywhere centrally on the system. Rather, it will install in a subdirectory of build, where temporary files are kept. You could set the destinationDir property on the task to remedy this.
You can created a distribution archive (zip, tar.gz) which can be downloaded by the user and only needed to unpack and add the bin folder to the path.
The problem is that you can't automatically enhance you path environment variable. But if you use the generated scripts from appassembler-maven-plugin you can simply can call directly the generated scripts without enhancing your path. This works on linux as well as on windows.
This can be achieved by a combination of appassembler-maven-plugin and maven-assembly-plugin.
The appassembler-maven-plugin will create the appropriate shell/bat/cmd files for you and the maven-assembly-plugin can create the appropriate archives (tar.gz, zip) for you.
As an example you can take a look here:
https://github.com/khmarbaise/supose/tree/master/supose-assembly
"make install" works by copying your built artefacts into their target location. This behaviour is quite easy to emulate in ANT, because like make it allows you to specify your own build logic:
<target name="install" description="Copy binaries into install location">
<mkdir dir="/opt/myapp/bin"/>
<copy file="${dist.dir}/myproject.jar" todir="/opt/myapp/bin"/>
<copy file="${dist.dir}/myproject.sh" todir="/opt/myapp/bin"/>
<chown owner="${install.owner}">
<fileset dir="/opt/myapp" include="**/*"/>
</chown>
</target>
Course you'd have to run this target as root:
ant build
sudo ant install
Maven on the other hand is a highly opinionated build tool that does not support this kind of workflow. Why? This is really a deployment action. Of course you can customize the Maven setup using ant ANT plugin, but I'd advise to just have a shell script you run afterwards. Lot easier to understand:
mvn install
sudo install_myapp.sh
The script can pickup the built jar from the Maven local repository "$HOME/.m2/repository" or better still download it from a Maven repository!
You have other mvn goals like 'mvn deploy' and 'mvn install' that do what you need.
Related
I want to be set an archetype for a stable JavaFX (Java 8) Maven build that will produce an executable JAR that (always) runs from the command line. And preferable without needing to build an UberJar or similar.
When we use the Netbeans 'Maven JavaFX' archetype the resultant JAR file following a build runs. As a project grows we find that sometimes the JAR won't run from the command line. Some Maven POM edits have been needed to 'encourage' the program to run from the command line again. This applies to Linux and Windows.
This also happens directly with the ZenJava JavaFX archetype, e.g. a project artifactId=xx:
java -jar target\xx.jar
no main manifest attribute, in target\xx.jar
This is just from the mavan generate command. The details of the two archetypes in question are:
zenjava
archetypeArtifactId=javafx-basic-archetype
archetypeGroupId=com.zenjava
netbeans
archetypeArtifactId=javafx
archetypeGroupId=org.codehaus.mojo.archetypes
Comparing the resulting POM files shows these that the codehaus.mojo (netbeans) uses these plugins in the build:
maven-dependency-plugin
maven-compiler-plugin
exec-maven-plugin
Either project runs happily from within Netbeans IDE. The challenges occur when we want to test on command line. It isn't really the best look externally when the build looks unstable to outsiders like that.
The questions arising are about what are the requirements to make a JavaFX command-line executable JAR file? For JDK 8 and beyond.
Is there an alternative JavaFX archetype available that will build projects with dependent JAR-s and run from the command line?
What allows Netbeans (say) to execute JAR when the same the built JAR won't run on the command-line?
What 'magic' does Netbeans be add to the execute step?
What is needed for the zenjava archetype to run "Java -jar"?
The JAR resulting from the follow steps doesn't run on the console.
mvn archetype:generate -DarchetypeGroupId=com.zenjava -DarchetypeArtifactId=javafx-basic-archetype ... -DartifactId=xx
mvn install
java -jar target/xx-001.jar
What influences the: maven-dependency-plugin and maven-compiler-plugin when building the JAR for bigger projects?
In other words, what assumptions might be being broken a project grows and bind with other JAR files.
Needless to say, the Maven generate and build steps are using the JDK Java environment. The execution though, java -jar target/xx-001.jar, need to run under the simple JRE (without the JDK). I guess question #4 is a long stretch unless you are someone who has a biggish JavaFX project and solved this already. Suggestions welcome.
just to mention: I'm the maintainer of the javafx-maven-plugin (and the archetype).
To answer your question 3:
You have to call the GENERATED jar-file from the plugin, which is located at target/jfx/app/yourapp.jar
The generated jar-file will reference all required dependencies, which are noted inside the META-INF/MANIFEST.MF-file inside it. While creating that jar-file, the pom is scanned for runtime-dependencies, these will be placed at the target/jfx/app/lib-folder. When bundling your app into native bundle, the JRE is put aside of the generated launcher under the target/jfx/native/-folder.
What confuses me about your problem: mixing CLI- and GUI-application might result in problems, but i guess it's just your special requirement :)
EDIT:
Calling mvn install does NOT generate jfx-jar without special configuration, you have to call mvn jfx:jar or mvn jfx:native to call the MOJOs of the plugin. For easier configuration, please visit our configuration-website: http://javafx-maven-plugin.github.io/
I'm hacking on a Maven-based project with a lot of dependencies; the project is normally meant to be developed in Eclipse but I need to work on it from the command line.
How to build+execute the project in a sane way? Something like mvn run, but of course Maven is not meant for running Java projects (for some reason).
The problem is specifying all the dependencies on java's commandline, I don't even know how to autogenerate that. I can currently deal with it using the assembly:single maven plugin (using the jar-with-dependencies descriptor) which will package the dependencies to a single .jar for me.
However, there really is a lot of dependencies and the assembly phase can take about two minutes, greatly disrupting my hack-test cycles so I'm looking for other ways to run the project with minimum build overhead - any recommendations, please?
Note: One possibility is running it in Eclipse once and capturing the java commandline. However, that's just a one-time hack, not a general solution in case I change pom.xml later or come to another project from the suite without Eclipse access anymore.
Have a look at the maven exec plugin
mvn exec:java -Dexec.mainClass="com.example.Main"
if you do this frequently, you can of course configure it via plugin configuration.
Regarding finding out project dependencies - you can use maven dependency plugin
http://maven.apache.org/plugins/maven-dependency-plugin/list-mojo.html
If you want to put them into file it'd be smth like
mvn dependency:list > dependencies.txt
See this question: How can I create an executable JAR with dependencies using Maven?. You can use the dependency-plugin to generate all dependencies in a separate directory before the package phase and then include that in the classpath of the manifest.
I see three solution to this:
onejar-maven-plugin - faster than assemlby with jar-with-dependencies descriptor
With onejar-maven-plugin, you'll (...) get a nice clean super jar with the dependency jars inside.
Spring Boot Maven Plugin - but this is dedicated to Spring projects
Maven Assembly Plugin with custom descriptor. This custom descriptor should grab all dependencies into lib folder, maven-jar-plugin should set Class-Path in Manifest.fm according to this new location. After this you can simply execute your program or zip your jar with lib folder as distribution.
After this is possible to run your program on your computer or any other with one command:
java -jar myjar.jar
I'm trying to use Google protocol buffer for Java(I'm a newbie about Java, just trying).
First of all, I'm using OSX and I've installed protocol buffer with brew install protobuf command.
protoc command works okay.
I've generated MyProtocol.java by protoc.
I've installed protocol buffer for Java as its instruction(README.txt).
mvn install command created .m2 directory and I can find protobuf-java-2.4.1.jar file somewhere in the directory.
I wrote simple test Java code just importing MyProtocol.java and it complains could not find package com.google.protobuf.
So, I've just make jar file mvn package and add its directory as CLASSPATH and it compiled well.
javac -classpath <protobuf-dir>/jara/target/classes Test.java ./com/example/tutorial/AddressBookProtos.java
If I use maven's repository directory (~/.m2/repository), it complains again.
Doesn't maven make CLASSPATH for me if I install the package?
If not, how can I use installed package by maven to compile my code?
The Maven Dependency Plugin has a goal called build-classpath which does what you need. You can get usage hints on the Usage page
Maven doesn't change your setup, so it's up to you to set your CLASSPATH according to your need.
However there are at least two ways in which Maven can halp you:
You can use the Maven Assembly plugin to collect all your dependencies in a directory or an archive, so that you only need to add a single directory to your CLASSPATH in order to run your program;
You can use the Exec Maven plugin to add the running of your program as a goal in your POM and then run it with Maven.
Java newbie here. I'm trying to run the latest version of MWDumper, which is a command-line utility that imports wiki databases. The page said I should build it from its source. I've downloaded the source-code. They've got a makefile and a build.xml. How do I build this?
You need to install ANT and run ANT in the folder containing the build.xml.
If you're on linux or mac it's pretty easy - you just [package manager name here] install ant;
You then just cd to the appropriate folder and type in ant. It should build your app.
You also need to make sure that you have the Java Development Kit installed for the ANT to use. Ant doesn't actually do any compiling, it's just a tool that reads build instructions and calls various applications and compilers to output the end executable (or similar product).
You should be able to install 'jdk' from your package manager, or from their site (http://www.oracle.com/technetwork/java/javase/downloads/index.html).
If you're on Windows, you can install the JDK from the same link, and you can follow the following link as a guide to install ant for windows: http://ant.apache.org/manual/install.html
Don't forget to add the path to ant to your environment 'PATH' variable! :) (more details in the link above)
Use Apache Ant.
cd <dir>
ant <target>
Also you can use Apache Maven.
cd <dir>
mvn install
I was wondering if there is a standard way (i.e. a plugin) to apply a set of patches during a Maven build. Patching the code base in a dedicated step before building is getting tedious as soon as you have different builds or generated sources.
To give an example, this script should deploy 3 different versions from a fresh SVN checkout:
#!/bin/bash
# checkout project
svn checkout http://example-project.googlecode.com/svn/tag/v1_0 example-project-read-only
cd example-project-read-only
# build example-project-1.0
mvn deploy
# build example-project-1.0-a3
mvn -Dmaven.patch.dir=/path/to/patchesA -Dmaven.patch.buildSuffix=a3 clean patch:patch deploy
# build example-project-1.0-b0
mvn -Dmaven.patch.dir=/path/to/patchesB -Dmaven.patch.buildSuffix=b0 clean patch:patch deploy
Currently I'm doing similar things with another build script I'd like to get rid of. Therefore I'm considering to write such a plugin if it's not available yet. (Maybe with dedicated patch artifacts for easy distribution as an added bonus?)
The maven patch plugin might help.
The Patch Plugin has a single goal that can apply either a single declared patch or a directory of patches. Application of an entire patch directory can be configured with various patch-inclusion, -exclusion, and -ordering options:
I haven't heard of any such plugin. However I imagine that you could do something with profiles that applied patches and conditionalized the build dir. Sounds interesting.