Some clarifications about how ant copy some files into a folder? [duplicate] - java

This question already has an answer here:
Some clarification about how ant copy some files into a folder?
(1 answer)
Closed 8 years ago.
I am pretty new to ant (I came from Maven and Ant is a nightmare for me !!!)
I have this target:
<target name="linuxdriver"
description="Linux Driver">
<copy file="${deps.linuxdriver.dir}/${deps.linuxdriver.name}"
tofile="${project.datadir}/${deps.linuxdriver.name}"/>
<copy file="${deps.linuxdriver.dir}/${deps.linuxdriver.name}"
tofile="${project.deploy}/data/${deps.linuxdriver.name}"/>
<chmod perm="+x" file="${project.datadir}/${deps.linuxdriver.name}"/>
<chmod perm="+x" file="${project.deploy}/data/${deps.linuxdriver.name}"/>
</target>
and I have also a property file in which there is definied the "variable" (are named variable?) used in the previous ant code, specifically I have:
project.datadir = ${basedir}/data
project.deploy.dir = Release
project.deploy = ${basedir}/../${project.deploy.dir}
deps.linuxdriver.name = atmosfs
And now I have some doubts:
1) What represents ${basedir}? A specific directory? What? Reading on the ant manual (http://ant.apache.org/manual/properties.html) say that this is: the absolute path of the project's basedir (as set with the basedir attribute of ).
So, is it the absolute path of my project in the Eclipse workspace?
2) Using the previous information what exactly are the two destination folder in which the files are copied (using the "copy file...to file" tag)?

1) What represents ${basedir}? A specific directory?
Yes. ${basedir} is the directory where you either started Ant, or the directory specified in the <project> entity on the top of your Ant file. Normally, it is set to "." which makes it the same directory as the directory that contains your Ant build file.
2) Using the previous information what exactly are the two destination folder in which the files are copied (using the "copy file...to file" tag)?
You didn't list your whole Ant file, and your whole properties file. I'm not even sure if your properties file is read in (You need a <property file="xxxx.properties"/> near the top of your Ant file).
Assuming that you are executing this in the same directory as your Ant file, and your ${basedir} is the same directory as your Ant file:
<copy file="${basedir}/atmosfs/atmostfs"
verbose="true"
tofile="${basedir}/Release/atmosfs"/>
<copy file="${basedir}/atmofs/atmofs"
verbose="true"
tofile="${basedir}/../Release/data/atmofs"/>
Again, I am assuming ${basedir} is the directory where your Antfile is stored, and that you are executing the script from that directory.
Notice I have verbose="true" in the <copy>. I recommend you make that change. This will show you what file is being copied and where when <copy> is executed. It's probably the best way to handle this.
By the way, one rule I have is that all action takes place in the project tree. Your last tofile is being written outside of the project directory (where I assume your Ant file is located). Imagine someone checking out the project, and finding out that the build process wrote a file outside of the checked out directory and onto his computer in a random place. Doing this is just considered impolite.
Even more polite is to write all files and do all build processing under a subdirectory. Some people use build, I prefer target because that's a Maven standard. THe idea is that I can clean up the entire build process by simply deleting that one directory.

Related

Ant jar task - Include files not underneath basedir

I am trying to write an ant target that will create a jar based on a bunch of java files and some properties files, but am having trouble including the properties files the way the project is set up currently.
These are the ant targets I have:
1 - Compile the java souce files from the "myjar.src" folder and put the resulting classes into a "myjar.classes" folder. Once this is done copy all non .java files from "myjar.src" to "myjar.classes".
2 - Create the jar using the "jar" command using basedir = ${myjar.classes} and tell it to include everything.
These are the ant targets I want:
1 - Compile the java souce files and put the resulting classes into a "myjar.classes" folder. Only .java files are included
2 - Create the jars using the "jar" command using basedir = ${myjar.classes.location} but also include the .properties and .xml files from "myjar.src."
The key difference is I want the properties and xml files from "myjar.src" to be included when I package up the classes in "myjar.classes" using basedir = ${myjar.classes} - How do I include these fies when they are not underneath "myjar.classes"?
This is the ant target I want to modify:
<CreateManifest title="myjar classes etc"/>
<jar
destfile="${myProject.build.jars.dir}\ta_test_driver.jar"
basedir="${myjar.classes}"
manifest="${manifest}">
<include name="**"/>
</jar>
The reason I am not just using a directory one level up for basedir is that none of the other jar creation calls in the project do that, and I am hesitant to change that for just this one. I did try to do that, but had trouble specifying the right directory. (There are other jars that use a similar directory structure, and I don't want to interfere with them either now or in the future.) I was just wondering if these is a better way to do this? Thanks very much.
I managed to figure this out from here: How to include file in Jar through Ant at specific location
This was my modified ant call in the end:
<CreateManifest title="myjar classes etc"/>
<jar
destfile="${myProject.build.jars.dir}\ta_test_driver.jar"
basedir="${myProject.classes}\ta_test_driver"
manifest="${manifest}">
<include name="**"/>
<zipfileset dir="${myjar.src}"
includes="**/*.xml, **/*.properties, **/*.gif"
/>
</jar>
Notice the zipfileset tag.

Launch4J - how to attach dependent jars to generated exe

I have a simple java project, which requires external jars.
I build this with netbeans and after Clean and Build command, I can find in dist directory the following structure:
-myApp.jar
-lib/
library1.jar
library2.jar
typical, I would say.
Now, I'd like to distribute myApp.jar with dependent libraries as one exe.
Is this possible? I am trying to use Launch4J. In the GUI I create the config file, there are some options in cp section
<cp>lib/swing-layout-1.0.4.jar</cp>
but it seems to be classpath, and it is the only place I can refer to my extra jars.
After exe file is created, I can't find dependend libs in the exe (exe can be opened with winrar) and thus my application crashes.
How can I make the exe file properly then?
Thanks for your help.
As it often happens being unable to solve the problem I published it on StackOverflow ... and pretty soon after publishing the question I got an idea.
So the answer to my question is:
Put all the dependent jars into one main jar.
It took me some time to find info how can I do that.
To help people I decided to publish detailed instruction here - they are based on Netbeans 7.4.
Following article from http://mavistechchannel.wordpress.com/2010/08/17/how-to-build-a-single-jar-file-with-external-libs/ I created the ant script that build one-jar-app for me.
I could then manually create exe via Launch4J
I then decided that I want more automated task, and I did that, Ant builds exe for me (via Launch4J)
Then I realized that I must do "clean and build" before my automated task (in point 2)/ I decided that I want clean and build to be done automatically before the exe build
Putting all together I am attaching my ant build script consisting of points 1,2,3:
It is required to edit build.xml and put the content found below before "project" end tag
<target name="package-for-launch4j" depends="clean,compile,jar">
<property name="launch4jexe.dir" location="C:\Program Files (x86)\Launch4j" />
<taskdef name="launch4j"
classname="net.sf.launch4j.ant.Launch4jTask"
classpath="${launch4jexe.dir}/launch4j.jar
:${launch4jexe.dir}/lib/xstream.jar" />
<property name="launch4j.jar.name" value="MyAppJarName"/>
<property name="launch4j.dir" value="exe"/>
<property name="launch4j.jar" value="${launch4j.dir}/${launch4j.jar.name}.jar"/>
<echo message="Packaging ${application.title} into a single JAR at ${launch4j.jar}"/>
<delete dir="${launch4j.dir}"/>
<mkdir dir="${launch4j.dir}"/>
<jar destfile="${launch4j.dir}/temp_final.jar" filesetmanifest="skip">
<zipgroupfileset dir="dist" includes="*.jar"/>
<zipgroupfileset dir="dist/lib" includes="*.jar"/>
<manifest>
<attribute name="Main-Class" value="${main.class}"/>
</manifest>
</jar>
<zip destfile="${launch4j.jar}">
<zipfileset src="${launch4j.dir}/temp_final.jar"
excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/>
</zip>
<delete file="${launch4j.dir}/temp_final.jar"/>
<launch4j configFile="misc/l4j-myapp.xml" />
</target>
then in Netbeans rightclick on the build.xml and choose:
Run Target / Other Targets / package-for-launch4j
exe file is ready in exe folder :-)
When you are converting your .jar file
Go to classpath tab
Check custom classpath
On main class select your .jar from your dist folder after building the project
On the classpath textarea add your libraries, you add them right below that
textarea writting the full path to the lib (of course including the
lib, ie "C:\folder\lib\file.jar")
I have spent hours on this issue. So here is my contribution.
The problem here: how to sucessfully put your external jars that your .JAR program needs INSIDE the .exe that you generate.
We assume that you already, and correctly, configured the external jars on eclipse/netbeans and ALL WORK FINE with the command: java -jar yourprogram.jar.
So the real problem is how to ensure that this .EXE file will contain the external jars, otherwise it will not work properly.
1) First of all, you need to forget Launch4J and anyother program.
2) Install JSmooth, I recommend that you use the windows version.
3) On the left menu there is a button "Application". Click on it.
4) You will see a tab "Classpath" panel. Click on the plus (+) and add your external .jar's files. And that is it!!
Don't forget to put your .jar application marking checkbox "use am embedded jar" and choose the main class properly. It will work.
I also faced the same issue while migrating my .jar to exe. I also had many dependent libraries as well. So These were the steps I performed :
Download and Install launch4j.
Open your project in netbeans. Clean and build the project.
Make sure you have a folder named 'dist' in the project directory. It will have your jar files with lib folder(containing the dependent libraries).
Open launch 4j.
Create output file in the dist folder. For example : OutputFile : D:******\My_App\dist\my_application.exe
Browse your jar file in the next row. For example : Jar : D:******\My_App\dist\my_application.jar
Go to classpath tab. Tick CustomClasspath. Press browse icon, and browse to your jar file which is located in the dist folder.
Specify Min Jre version in the JRE tab.
Save the configration.
Build the wrapper(by clicking the settings icon)
Your exe file will be generated in the dist folder.
Thats it :)
Putting different links of places which had helped me
How to include all dependent Jars within a single non-executable jar?
How can I create an executable JAR with dependencies using Maven?
http://www.mkyong.com/java/how-to-make-an-executable-jar-file/
and most importantly
http://docs.oracle.com/javase/tutorial/deployment/jar/manifestindex.html
quick tut
http://www.mkyong.com/java/how-to-add-your-manifest-into-a-jar-file/
To include external libraries with Launch4j you have to have the ".jar" files of the external libraries near your .exe (mine are just in the same folder) then in "Classpath" you put in the path to the .jar files into "Edit Item: "
In launch4j go to the classpath tab. Tick the custom classpath field. In the edit field, enter the full path of each jar you want included and press accept. When finished type just the name of the main class into the separate field (ie MyProg). All the jars will now be included in the exe.
PS I have all the jars in the same directory. I'm using version 3.12

Some clarification about how ant copy some files into a folder?

I am pretty new to ant (I came from Maven and Ant is a nightmare for me !!!)
I have this target:
<target name="linuxdriver"
description="Linux Driver">
<copy file="${deps.linuxdriver.dir}/${deps.linuxdriver.name}" tofile="${project.datadir}/${deps.linuxdriver.name}"/>
<copy file="${deps.linuxdriver.dir}/${deps.linuxdriver.name}" tofile="${project.deploy}/data/${deps.linuxdriver.name}"/>
<chmod perm="+x" file="${project.datadir}/${deps.linuxdriver.name}"/>
<chmod perm="+x" file="${project.deploy}/data/${deps.linuxdriver.name}"/>
</target>
and I have also a property file in which there is definied the "variable" (are named variable?) used in the previous ant code, specifically I have:
project.datadir = ${basedir}/data
project.deploy.dir = Release
project.deploy = ${basedir}/../${project.deploy.dir}
And now I have some doubts:
1) What represents ${basedir}? A specific directory? What?
2) Using the previous information what exactly are the two destination folder in which the files are copied (using the "copy file...to file" tag)?
That concept of basedir is described in the ANT manual:
Built-in properties
Writing a simple Buildfile
It's normally set to be the directory from where you run the build (can be overridden).
If you need to see how properties are resolved, consider running your build in debug mode

How to add resources to classpath

How do you add a folder (e.g. a resource folder containing arts) to the classpath of a netbeans project? I managed to do that manually via editing the NB generated jar file of the project (that is its MANIFEST.MF file + copying the resources manually), but there should be a way to tell netbeans as well to mind the resources, no?
The folder structure looks like this:
/project/art/
/project/dist/lib/
/project/dist/art/
/project/dist/project.jar
/project/lib/
/project/src/
I don't want to package the art into the jar because I'd like the art to be easily exchangeable. If I add the art folder to the src folder then NB compiles fine, but the art resources end up in the jar.
Adding the art folder to the netbeans project libraries (Properties -> Libraries -> Add JAR/Folder) seemed not to work, because then I ended up with an error '...\project\art is a directory or can't be read. Not copying the libraries.' which in turn prevents even the real libraries folder from being copied.
Any ideas?
Best regards
Chris
2 Observations made, based on the comments from gpeche:
a) Rather specifying the additional resources folder in the "Run" tab than in the "Compile" tab of the project properties -> Libraries doesn't seem to make a lot of difference in Netbeans (I'm currently using 6.9.1). The output (and thus error) stays the same, that is nothing gets copied at all:
Created dir: C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\dist
C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\art is a directory or can't be read. Not copying the libraries.
Not copying the libraries.
Building jar: C:\Users\Chrisi\Desktop\vocabulary\VocabularyTrainer\dist\VocabularyTrainer.jar
Another interesting aspect is that in the help menu of the Libraries panel nothing is explicitly mentioned regarding folders as libraries. Could it be possible, that the button in Netbeans is falsely named, that is only real jar's are allowed?
b) Adding the resources folder to the Libraries list does have the impact though, to add another entry to the MANIFEST.MF. While - and that's the smaller issue - the classpath entry seems to be always expecting the resource folder to be a subfolder of the library folder (e.g. "lib/arts") the major problem is that there seems to be a slash missing.
As mentioned the NB generated entry in the MANIFEST.MF will look like this "lib/arts" (which does not work for me), while (manually set) "lib/arts/" does?!
The way I use resources from the folder is something like this:
URL resource = getClass().getResource("/gui/refresh.png");
ImageIcon tmp = new ImageIcon(resource);
Edit:
Based on Tushars comment and this posting I found the following solution to be an acceptable tradeoff between functionality and comfort.
I override the ANT target from the auto generated 'build-impl.xml' file which creates the Class-Path in the MANIFEST.MF file in the basic 'build.xml' file of the Netbeans project. The code which goes to the 'build.xml' file looks like this:
<property name="art.classpath" value="art/" />
<target name="-post-jar">
<mkdir dir="${dist.dir}/art"/>
<copy todir="${dist.dir}/art">
<fileset dir="${basedir}/art">
<!-- <exclude name="**/!source/**"/> if you want to exclude something... -->
</fileset>
</copy>
</target>
<target name="-init-macrodef-copylibs">
<macrodef name="copylibs" uri="http://www.netbeans.org/ns/j2se-project/3">
<element name="customize" optional="true"/>
<sequential>
<property location="${build.classes.dir}" name="build.classes.dir.resolved"/>
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
</pathconvert>
<pathconvert pathsep=" " property="jar.classpath">
<path path="${run.classpath.without.build.classes.dir}"/>
<chainedmapper>
<flattenmapper/>
<globmapper from="*" to="lib/*"/>
</chainedmapper>
</pathconvert>
<taskdef classname="org.netbeans.modules.java.j2seproject.copylibstask.CopyLibs" classpath="${libs.CopyLibs.classpath}" name="copylibs"/>
<copylibs compress="${jar.compress}" index="${jar.index}" jarfile="${dist.jar}" manifest="${manifest.file}" runtimeclasspath="${run.classpath.without.build.classes.dir}">
<fileset dir="${build.classes.dir}"/>
<manifest>
<attribute name="Class-Path" value="${jar.classpath} ${art.classpath}"/>
<customize/>
</manifest>
</copylibs>
</sequential>
</macrodef>
</target>
The tradeoff is that for development in Netbeans I still have to add the resource folder (e.g. 'art') to the libraries list to make the project run in Netbeans. This will cause an additional entry in the MANIFEST.MF file ('lib/art') along with the effect that the libraries will not get automatically copied to the 'dist' folder, with the message
...\art is a directory or can't be read. Not copying the libraries.
Not copying the libraries.
This behavor is - afaik - intended (to force everything to be bundled up in a jar), even though there are discussions about it going on. To make a real distribution bundle I'd have to take away the resource folder(s) from the library list in NB and rebuild.
Ideas about a more streamlined setup without any tradeoffs are of course still welcome. :)
Adding resource folder to classpath:
When you Clean-&-Build a NetBeans Ant Based Project it creates a manifest.mf file in the root directory of the project. This file gets included in the JAR file also. Modify this file and add entry like follows:
Manifest-Version: 1.0
X-COMMENT: Main-Class will be added automatically by build
Class-Path: arts/
slash is important after arts in the class path.
Including the arts resource folder in the distribution
Either copy this folder in the dist folder after the build or add a ANT target to copy the required resources in the dist folder.
Add the target like as follows in the build.xml file:
<target name="-post-jar">
<mkdir dir="${dist.dir}/resources"/>
<copy todir="${dist.dir}/resources">
<fileset dir="${basedir}/resources" />
</copy>
</target>
Code to access such resources:
The code needed to access such resource files shall be as follows: (This will not work in design time but surely from the JAR file)
// pay attention to relative path
URL resource = ClassLoader.getSystemResource("gui/refresh.png");
ImageIcon tmp = new ImageIcon(resource);
NOTE: The files manifest.mf and build.xml located in the root directory of the project are accessible from the Files Panel in NetBeans IDE
Using NetBeans 8.0.2:
Right-click the project.
Select Properties.
Select Sources.
Click Add Folder for the Source Package Folders.
Select the the directory where the resources exist.
Click Open on the directory name.
Click OK to close the Project Properties dialog.
The resources are added to the project.
You'll see the directory added in your Navigation pane as well
In the other project, the resources are now available. For example, to read an image:
BufferedImage zero = ImageIO.read(OCR.class.getResourceAsStream("/0.bmp"));
In order to remove the lib/art from Class-Path and not get "is a directory or can't be read" need delete lib/art from path:
<pathconvert property="run.classpath.without.build.classes.dir">
<path path="${run.classpath}"/>
<map from="${build.classes.dir.resolved}" to=""/>
**<map from="${basedir}/art" to=""/> <!-- remove art from lib -->**
</pathconvert>

Build project into a JAR automatically in Eclipse

I have an Eclipse project where I want to keep my Java project built into a JAR automatically. I know I have an option to export the project into a JAR; if I do a right click; but what I am really looking for is, that like Eclipse automatically builds a project's .class files and put them in target folder; it should also build a JAR automatically and copy the latest JAR at some or a specific location.
Is there a option to configure Eclipse in such a way, to build JARs automatically?
Just to make it clear for guys, patient enough to answer my question; I am not looking at ANT as solution; as I already use it, but what I would like it something that gets initiated automatically either with a time based trigger or immediate build with change.
You want a .jardesc file. They do not kick off automatically, but it's within 2 clicks.
Right click on your project
Choose Export > Java > JAR file
Choose included files and name output JAR, then click Next
Check "Save the description of this JAR in the workspace" and choose a name for the new .jardesc file
Now, all you have to do is right click on your .jardesc file and choose Create JAR and it will export it in the same spot.
Create an Ant file and tell Eclipse to build it. There are only two steps and each is easy with the step-by-step instructions below.
Step 1
Create a build.xml file and add to package explorer:
<?xml version="1.0" ?>
<!-- Configuration of the Ant build system to generate a Jar file -->
<project name="TestMain" default="CreateJar">
<target name="CreateJar" description="Create Jar file">
<jar jarfile="Test.jar" basedir="." includes="*.class" />
</target>
</project>
Eclipse should looks something like the screenshot below. Note the Ant icon on build.xml.
Step 2
Right-click on the root node in the project.
- Select Properties
- Select Builders
- Select New
- Select Ant Build
- In the Main tab, complete the path to the build.xml file in the bin folder.
Check the Output
The Eclipse output window (named Console) should show the following after a build:
Buildfile: /home/<user>/src/Test/build.xml
CreateJar:
[jar] Building jar: /home/<user>/src/Test/Test.jar
BUILD SUCCESSFUL
Total time: 152 milliseconds
EDIT: Some helpful comments by #yeoman and #betlista
#yeoman I think the correct include would be /.class, not *.class, as most
people use packages and thus recursive search for class files makes
more sense than flat inclusion
#betlista I would recomment to not to have build.xml in src folder
Check out Apache Ant
It's possible to use Ant for automatic builds with eclipse, here's how
This is possible by defining a custom Builder in eclipse (see the link in Peter's answer). However, unless your project is very small, it may slow down your workspace unacceptably. Autobuild for class files happens incrementally, i.e. only those classes affected by a change are recompiled, but the JAR file will have to be rebuilt and copied completely, every time you save a change.
Regarding to Peter's answer and Micheal's addition to it you may find How Do I Automatically Generate A .jar File In An Eclipse Java Project useful. Because even you have "*.jardesc" file on your project you have to run it manually. It may cools down your "eclipse click hassle" a bit.
Using Thomas Bratt's answer above, just make sure your build.xml is configured properly :
<?xml version="1.0" ?>
<!-- Configuration of the Ant build system to generate a Jar file -->
<project name="TestMain" default="CreateJar">
<target name="CreateJar" description="Create Jar file">
<jar jarfile="Test.jar" basedir="bin/" includes="**/*.class" />
</target>
</project>
(Notice the double asterisk - it will tell build to look for .class files in all sub-directories.)
Creating a builder launcher is an issue since 2 projects cannot have the same external tool build name. Each name has to be unique. I am currently facing this issue to automate my build and copy the JAR to an external location.
I am using IBM's Zip Builder, but that is just a help but not doing the real.
People can try using IBM ZIP Creation plugin.
http://www.ibm.com/developerworks/websphere/library/techarticles/0112_deboer/deboer2.html#download

Categories