Maven Multiple platform dependent Packages - windows

I have written an application in Java that can be used on both Linux and Windows. Currently by running mvn package, my maven build system will generate a .msi using WiX.
Is there a way of creating two package 'tasks' so I can say either mvn package-windows ormvn package-linux`

If you want to package both versions (Linux and Windows), you can bind your mvn package phase to an extra phase that would build another artifact.
...
<plugin>
<groupId>org.group.extra</groupId>
<artifactId>extra-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
[...]
</configuration>
<goals>
<goal>package</goal>
</goals>
</execution>
</executions>
</plugin>
...
It was probably what you have already done with maven-wix-plugin.

You can use either use profile to do that or a better thing would be to have three project.
One for the core and then one for Linux and one for Windows that uses the core project.

Related

maven - generate sources is not working

please advise if possible on this
I am running mvn package source:jar and get a module.jar and module-sources.jar as expected in the target directory
However, I have 2 issues:
1) I when I do : mvn install source:jar I get a -source.jar in my "target" in
the local projects folder, HOWEVER, NOT in the "local-repository (under .m2
on my PC). Even though, I do get a module.jar with binaries installed.
EDIT: I have figured this item (1): It works if I place "source:jar" before "install". That is mvn source:jar install instead of mvn install source:jar
2) I want to NOT HAVE TO run source:jar in the command line to generate the sources. Because, when I use GO continuous integration tool, that I have no control over, they do not have a maven goal mvn source:jar there.
I know that with the configurations in the pom.xml it can be achieved, and I did see it occuring once or twice, but it stopped working (well, obviously I made a change,that I do not know that broke this)
My pom.xml has the following
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<outputDirectory>${source.directory}</outputDirectory>
<finalName>${project.jar.name}</finalName>
<fileNameMapping>no-version</fileNameMapping>
<classifier>${source.classifier}</classifier>
</configuration>
</execution>
</executions>
</plugin>
So, ultimately, when I run either mvn package or mvn install or I want to have sources generated as a jar file next to the regular project.jar (or in the specified folder, but it is not essential)

Setting Maven for scripting languages?

Maven is for building and managing any Java-based project. But what happens if a project is in a scripting language?
All maven can do now with TCL is copy the files around and put them in the right place in the target directory.
My problems are as follows:
Code is in TCL-> need of an interpreter not of a compiler.
It doesn't see any Java code, so it doesn't compile anything.
It doesn't see any Java tests, so it doesn't run them.
There's no java to run coverage against, so the jococo won't have anything to do.
Is there any way to set up maven for supporting a TCL project?
I've searched a lot in the internet and I found only 'jacl', but I don't really know how I can use it for setting up Maven.
Tcl isn't closely integrated with Maven (unlike Java) so you'll have to do more work. To run a Tcl script from Maven, the simplest way is to use the Exec Maven Plugin, but you have to bind the executions to explicit lifecycle phases yourself instead of relying on defaults. For example, to run a script during the test phase (i.e., to do tclsh testscript.tcl anotherArgument), you use:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<executions>
<execution>
<id>run-tcl-tests</id>
<phase>test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>tclsh</executable>
<arguments>
<argument>testscript.tcl</argument>
<argument>anotherArgument</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Maven's long-winded! Don't forget that you can probably put much of the complexity in a parent POM, and you can use properties and profiles to do interesting things.
You can also use the java goal to run Jacl or jTcl interpreters (in a sub-process). It depends on what exactly you want to do.
Unless you're using jTcl I don't see what Maven will do, apart from complicate your build process. Unless you understand Maven well and can develop some supporting plugins. As you've pointed out TCL is a scripting language, meaning your real challenge is a run-time deployment problem.
So, how would a TCL build process make deployment simpler? I would propose building RPM, Debian or MSI package for each targeted environment. These native installers can use dependency management to ensure the TCL interprertor is also installed. Another useful build option are starkits, which would bundle the TCL interpretor in a single file.
Once built, these binaries can be stored in your Maven repository (like jar files) and used as part of your deployment process. And finally don't forget you are not forced to use Maven as your build tool.
Disclaimer: Been a while since I've programmed with TCL, so hope this helps.
It is very much "not the maven way" to make dependencies on external build tools outside the maven ecosystem. Linking to tclsh will break your builds if tclsh isn't available. Not saying I haven't done worse (sometimes you just have to get it done and forget "the maven way"). Fortunately, there is an alternative - jacl.
First download the latest (probably 1.4.1) prebuilt jacl binary zip file from sourceforge.
Next, unzip and go into the lib/tcljava1.4.1 subdirectory. There are four jar files here you need to publish to your local repository (or another repo you use):
mvn install:install-file -Dfile=tjc.jar -DgroupId=jacl -DartifactId=tjc -Dversion=1.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=tcljava.jar -DgroupId=jacl -DartifactId=tcljava -Dversion=1.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=jacl.jar -DgroupId=jacl -DartifactId=jacl -Dversion=1.4.1 -Dpackaging=jar
mvn install:install-file -Dfile=itcl.jar -DgroupId=jacl -DartifactId=itcl -Dversion=1.4.1 -Dpackaging=jar
You'll also need to add these as dependencies to the project where you're calling the tcl script:
<dependency>
<groupId>jacl</groupId>
<artifactId>itcl</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>jacl</groupId>
<artifactId>jacl</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>jacl</groupId>
<artifactId>tcljava</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>jacl</groupId>
<artifactId>tjc</artifactId>
<version>1.4.1</version>
</dependency>
Then just call the tcl (or really jacl) script using the exec goal of the exec-maven-plugin, passing in the script file path as the first argument (customize the execution as necessary to bind to the proper phase, etc.):
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>runTcl</id>
<phase>process-resources</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Dbasedir=${basedir}</argument>
<argument>-classpath</argument>
<classpath/>
<argument>tcl.lang.Shell</argument>
<argument>${basedir}/src/main/scripts/myScript.tcl</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
Update: Note that I had to use the "exec" goal above instead of the java goal. That's because jacl calls System.exit() in it's main function, so it kills the jvm. With this config, you can fail the build by using:
package require java
java::call System exit 1
From within your tcl code (or any exit value other than zero or other successCodes configured in the plugin). Hope that helps.

Eclipse Maven multi module project with xmlbeans

I have a multi module project, in which one of the module ( say MODULE-A) generates sources and classes using xmlbeans plugin. So everytime when I do a clean install of parent project, eclipse recognizes all of the generated sources as new classes, and I don't want to commit the same files again and again when there is no schema change. To overcome this problem, I wrapped xmlbeans build under a profile so that I can build it with profile whenever there is a schema change. But it didn't solve the problem completely.
Whenever I try to do clean build of parent, MODULE-A is not creating 'schemaorg_apache_xmlbeans' under build directory ( which is something only generated by xmlbean plugin when I run with profile ). I can tell maven to exclude 'schemaorg_apache_xmlbeans' from the clean task. But I want to know if this is the right way to handle.
Appreciate your responses.
Thanks in advance
One alternative to this approach is to add this plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
This will allow the generated-sources to be added as a source folder so every time it generates you will have them built and available. You wouldn't commit these but when the actual jar gets built/released they will be in there and work all the same. This allows you to always be using code most up to date with your schema. This may not be the best solution for you but I found it to be a good idea when I ran into a similar situation.

maven dynamic version

I searching a way to dynamise the version of my artifact depending on the profile.
Often I use the -SNAPSHOT suffix when I build for dev or preprod. But the database connection depends on the profile and I never know if the latest SNAPSHOT version was build using the dev or preprod profile.
The idea would be having a version like this
<version>1.0${suffix}</version>
with ${suffix} =
"" when building with prod profile
"-SNAPSHOT" when building with preprod profile
"-DEV-SNAPSHOT" when building with dev profile
Is there a way of achieving this ?
thanks
edit :
My goal is when I go on jenkins to build my jar, I build the same "tagged" version of my project with the 3 profiles and it deploys 3 differents artifacts.
Actually I tag my project and go build with the prod profile, then I modify the version to add -SNAPSHOT, commit, move the tag, re build with preprod profile, and then repeat for the dev profile.
Seeing your answer to #Michael-O comments, i'd recommend to configure the maven assembly plugin to create the final name of the artifact according to a system property set on each profile. For example:
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>create jar according to profile</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>${project.artifactId}-${project.version}_${profile}</finalName>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
where ${profile} should be a property set to a different value on each profile (for doing that you can see this question). I dunno if there's a variable to get the profile being currently used to build, that would be another question :)
It is not necessary to reassemble the JAR, I would rather use a standard mech: Simply specify a classifier for your artifact in the jar plugin.
Otherwise I would filter a properties in a given properties file and read that in your app. This what I do, e.g. system.env=prod|test|localdev.

How should I get Maven to deploy artifacts for all supported architectures at the same time?

I have a question that's probably pretty similar to this. I need to solve what I have to imagine to be a pretty common problem -- how to configure Maven to produce multiple variations on the same artifact -- but I have yet to find a good solution.
I have a multi-module project, that eventually results in the assembly plugin generating an artifact. However, part of the assembly includes libraries that have changed substantially in the recent past, with the result that some consumers of the project need library version N, while others need version N+1. Ideally, we'd just automatically generate multiple artifacts, e.g. theproject-1.2.3.thelib-1.0.tar.gz, theproject-1.2.3.thelib-1.1.tar.gz, etc. (where that's release 1.2.3 of our project, running against either library version 1.0 or 1.1).
Right now, I have a bunch of default properties, which build against the latest version of the library in question, plus a profile to build against the older version. I can deploy one or the other this way, but cannot deploy both in one build. Here's the key wrinkle that differs from the above question: I can't automate build-one-clean-build-the-other inside of the release plugin.
Normally, we'd mvn release:prepare release:perform from the root of the multi-module project to take care of deploying everything to our internal Nexus. However, in that case, we have to pick one -- either run the old-library profile, or run without and get the new one. I need the release plugin to deploy both. Is this just impossible? I have to imagine we're not the first people who want to have our automated builds generate support for different platforms....
You may install additional artifacts with differrent types/classifiers. Use attach-artifact goal of the build-helper-maven-plugin to achieve this. Here is a small example - we are deploying a Windows and a Unix installers of the product as windows/exe and unix/sh files. These files will be installed to the local repo and deploy to the distribution management.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>install-installation</id>
<phase>install</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${basedir}/target/${project.artifactId}-${project.version}-windows.exe</file>
<classifier>windows</classifier>
<type>exe</type>
</artifact>
<artifact>
<file>${basedir}/target/${project.artifactId}-${project.version}-unix.sh</file>
<classifier>unix</classifier>
<type>sh</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
Hope this helps.

Resources