- 浏览: 731538 次
- 性别:
- 来自: 嘉兴
文章分类
- 全部博客 (386)
- Struts1.1 (2)
- Database (18)
- Core Java (15)
- Log4j (4)
- SSH (0)
- Dao (1)
- Architecture Design (1)
- References (2)
- Eclipse&MyEclipse (10)
- Hibernate (7)
- Spring (8)
- JavaMail (1)
- Data Structure And Algorithm (48)
- Struts 2 (2)
- SSI (1)
- SSL (2)
- JSTL (1)
- EJB3 (2)
- NET (2)
- XML (2)
- Components (2)
- Ant (3)
- Multi Thread (1)
- Performance Monitoring (1)
- Web Server (17)
- Oracle (1)
- jQuery (8)
- Regular Expression (1)
- Weblogic (1)
- Exception (1)
- Security (2)
- File Manipulation (1)
- JavaScript (12)
- JVM (2)
- HTML&DIV&CSS (4)
- Android (10)
- Beyond GFW (0)
- Business (0)
- SVN (6)
- 虚拟主机 (1)
- Virtual Host (3)
- My mentality (5)
- OS (15)
- ISPMP (3)
- Magento (5)
- Jsoup&HttpClient (7)
- LINUX (9)
- Database Design (0)
- Power Designer (1)
- TaobaoOpenPlatform (2)
- C/C++ (3)
- Maven (11)
- Quartz (1)
- Load Balance (1)
- Zabbix (4)
- Product&Business (1)
- Pay Interface (1)
- Tomcat (2)
- Redis (1)
- 集群 (1)
- Session (1)
- 共享Session (1)
- Jedis (1)
- jenkins (1)
- 持续集成 (1)
- Web前端 (1)
最新评论
-
aqq331325797:
特意注册账号上来说一句。牛逼!
swagger2.2.2 与 spring cloud feign冲突 -
KitGavinx:
跨顶级域名怎么保持sessionid一致?
Tomcat7集群共享Session 基于redis进行统一管理 -
jaychang:
dujianqiao 写道HI ,能否给一个完整的demo 啊 ...
淘宝订单同步方案 - 丢单终结者 -
GGGGeek:
找了一会儿,感觉mybatis应该没有这种操作,直到发现博主的 ...
mybatis collection list string -
dujianqiao:
HI ,能否给一个完整的demo 啊 ?
淘宝订单同步方案 - 丢单终结者
Top 15 Ant Best Practicesby Eric M. Burke , coauthor ofJava Extreme Programming Cookbook 12/17/2003 |
http://onjava.com/pub/a/onjava/2003/12/17/ant_bestpractices.html
<!-- ONJava MPU Ad -->
<!-- me -->
Before Ant, building and deploying Java applications required a hodgepodge of platform-specific scripts, makefiles, proprietary IDEs, or manual processes. Now, nearly every open source Java project uses Ant. A great number of companies use Ant for internal projects as well. The widespread use of Ant in these projects has naturally led to an increased need for a set of well-established best practices.
This article summarizes several of my favorite Ant tips or best practices. Many were inspired by mistakes made on previous projects, or from horror stories relayed to me from other developers. One person told me of a project where XDoclet-generated code was placed into a version- control tool that locks files. When a developer changes a source file, they must remember to manually check out and lock all of the files that will be regenerated. They must then manually run the code generator, and only then can they tell Ant to compile the code. Here are some problems with this approach:
- Generated code should not be stored in version control.
- Ant (or XDoclet, in this case) should automatically determine which files will be affected by the next build. Programmers should not have to figure this out manually.
- The Ant buildfile should define correct target dependencies so that programmers do not have to invoke targets in a particular order in order to get a good build.
<!-- <csperl file="set_book_cover_image"> --><!-- sidebar begins -->
Related Reading <!-- <csif perl="$cfg->vars('cover_image_url_base')"> --> <!-- <csperl>print $cfg->vars('cover_image_url_cat');</csperl> --> <!-- </csif> -->Java Extreme
Programming Cookbook
<!-- builds links to list in sidebar -->
<!-- csperl>
my @links = split(/(?:\r?\n)+/, ( $DATA{"supporting_links"} || "" ));
for my $link ( @links ) {
my ( $name, $url ) = split /=/, $link, 2;
next unless $name and $url;
$url = "http://oreilly.com/catalog/$DATA{'reference'}/$url" unless $url =~ /^\w+:/os;
$url = $url . "?CMP=ILL-4GV796923290";
if ($name =~ /Table of Contents/) {
print qq~ <a href="$url">$name</a><br /> \n ~;
} elsif ($name =~ /Index/) {
print qq~ <a href="$url">$name</a><br /> \n ~;
} elsif ($name eq "Author's Article") {
print qq~ <a href="$url">$name</a><br /> \n ~;
} elsif ($name =~ /Sample Chapter/) {
print qq~ <a href="$url">$name</a><br /> \n ~;
} else {
print qq~\n~;
}
}
</csperl-->
|
<!-- sidebar ends -->
When I start any new project, I begin by creating the Ant buildfile. Ant defines the build process and is used by every programmer on the team throughout the day. All of the tips in this article assume the Ant buildfile is an important artifact that must be written with care, maintained in version control, and refactored periodically. So here now are my top 15 Ant best practices.
<!-- sidebar begins --> <!-- don't move sidebars --> <!-- sidebar ends -->
1. Adopt Consistent Style Conventions
Ant users either love the XML buildfile syntax or hate it. Rather than jump into the middle of this fascinating debate, let's look at a few simple ways to keep the XML buildfile clean.
First and foremost, spend time formatting your XML so it looks visually appealing. Ant works with ugly or pretty XML, but ugly XML is hard to read. Provided you leave a blank line between targets, indent consistently, and avoid exceeding 90 or so columns of text, XML is surprisingly readable. Throw in a good editor or IDE that syntax highlights the XML, and you should not have any trouble getting by.
Also pick meaningful, human-readable names for targets and properties. For example, dir.reports is a better name than rpts . The specific naming convention is not important -- just come up with something and stick to it.
2. Put build.xml in the Project Root Directory
The Ant buildfile can reside anywhere, but putting build.xml in the top-level project directory keeps things simple and clean. This is the most common convention, and programmers expect to find build.xml in this location. Having the buildfile at the top directory also makes it conceptually easy to see how relative paths point to different directories in your project tree. Here is a typical project layout:
[root dir]
| build.xml
+--src
+--lib (contains 3rd party JARs)
+--build (generated by the build)
+--dist (generated by the build)
When build.xml
is in the top directory, you can compile code from
the command line without changing your working directory, provided
you are somewhere within the project directory tree. Just type this:
ant -find compile
. The -find
argument
tells Ant to search ancestor directories until it locates the
buildfile.
3. Prefer a Single Buildfile
Some people prefer to break up large projects into several small buildfiles, each of which is responsible for a small portion of the overall build. This is strictly a matter of opinion, but beware that breaking up the build often makes it harder to wrap your head around the overall process. Be careful not to over-engineer a clever hierarchy of buildfiles when a single file can usually do the job.
Even if your project is divided into many different buildfiles, programmers expect to find a master build.xml in the project root directory. Make sure this buildfile is available, even if it only delegates actual work to subordinate builds.
4. Provide Good Help
Strive to make the buildfile self-documenting. Adding target
descriptions is the easiest way to accomplish this. When you type
ant -projecthelp
, you see a listing of each target
containing a description. For example, you might define a target
like this:
<target name="compile"
description="Compiles code, output goes to the build dir.">
The simple rule is to include descriptions for all of the targets you wish programmers to invoke from the command line. Internal targets should not include description attributes. Internal targets may include targets that perform intermediate processing, such as generating code or creating output directories.
Another way to provide help is to include XML comments in the
buildfile. Or, define a target named help
that prints
detailed
usage information when programmers type ant help
.
<target name="help"
description="Display detailed usage information">
<echo>Detailed help...</echo>
</target>
5. Provide a Clean Target
Every buildfile should include a target that removes all generated files and directories, bringing everything back to its original, pristine state. All files remaining after a clean should be those found in version control. For example:
<target name="clean"
description="Destroys all generated files and dirs.">
<delete dir="${dir.build}"/>
<delete dir="${dir.dist}"/>
</target>
Do not automatically invoke clean
, unless perhaps you
have some special target for generating a full release. When
programmers are merely compiling or performing other tasks, they do
not want the
buildfile to perform a full cleanup before proceeding. This is both
annoying and counterproductive. Trust programmers to decide when
they are ready to clean all files.
6. Manage Dependencies Using Ant
Suppose your application consists of a Swing GUI, a web interface, an EJB tier, and shared utility code. In large systems, you need to clearly define which Java packages belong to which layer of the system. Otherwise, you end up being forced to compile hundreds or thousands of files each time you change something. Poor dependency management leads to overly complex, brittle systems. Changing the layout of a GUI panel should not cause you to recompile your servlets and EJBs.
As systems get bigger, it is easy to inadvertently introduce server-side code that depends on client-side code, or vice versa. This is because the typical IDE project compiles everything using a monolithic classpath. Ant lets you control the build more effectively.
Design your Ant buildfile to compile large projects in stages. First, compile shared utility code. Place the results into a JAR file. Then, compile a higher level portion of the project. When you compile higher-level code, compile against the JAR file(s) created in the first step. Repeat this process until you reach the highest level of the system.
Building in stages enforces dependency management. If you are working on a low-level framework Java class and accidentally refer to a higher-level GUI panel, the code will not compile. This is due to the fact that when the buildfile compiles the low-level framework, it does not include the high-level GUI panel code in the source path.
7. Define and Reuse Paths
A buildfile is often easier to understand if paths are defined once in a central location, and then reused throughout the buildfile. Here is an example that shows this in action.
<project name="sample" default="compile" basedir=".">
<path id="classpath.common">
<pathelement location="${jdom.jar.withpath}"/>
...etc
</path>
<path id="classpath.client">
<pathelement location="${guistuff.jar.withpath}"/>
<pathelement location="${another.jar.withpath}"/>
<!-- reuse the common classpath -->
<path refid="classpath.common"/>
</path>
<target name="compile.common" depends="prepare">
<javac destdir="${dir.build}" srcdir="${dir.src}">
<classpath refid="classpath.common"/>
<include name="com/oreilly/common/**"/>
</javac>
</target>
</project>
Techniques like this always gain more value as the project grows and the build gets progressively more complex. You will probably have to define different paths to compile each tier of the application, as well as paths to run unit tests, run the application, run XDoclet, generate JavaDocs, etc. This modular path approach is preferable to a gigantic path for everything. Failure to modularize makes it easy to lose track of dependencies.
8. Define Proper Target Dependencies
Suppose the dist
target depends on the
jar
target, which depends on compile
,
which depends on prepare
. Ant buildfiles ultimately
define a dependency graph, which must be carefully defined
and maintained.
Periodically review the dependencies to ensure that your builds do the right amount of work. Large buildfiles tend to degrade over time as more targets are added, so you end up with unnecessary dependencies that cause your builds to work too hard. For example, you might find yourself regenerating the EJB code when the programmer actually only wanted to compile some GUI code that does not use EJB at all.
Omitting dependencies in an effort to "optimize" the build is another common mistake. This is a mistake because it forces programmers to remember to invoke a series of targets in a particular order in order to get a decent build. A better solution exists: provide public targets (those with descriptions) that contain correct dependencies, and another set of "expert" targets that let you manually execute individual build steps. These steps do not guarantee a complete build, but let expert users bypass steps during quick and dirty coding sessions.
9. Use Properties for Configurability
Any piece of information that needs to be configured, or that might change, should be defined as an Ant property. The same is true for values that are used in more than one place in the buildfile. Properties should be defined either at the top of a buildfile or in a standalone properties file for maximum flexibility. Here is how properties look when defined in the buildfile:
<project name="sample" default="compile" basedir=".">
<property name="dir.build" value="build"/>
<property name="dir.src" value="src"/>
<property name="jdom.home" value="../java-tools/jdom-b8"/>
<property name="jdom.jar" value="jdom.jar"/>
<property name="jdom.jar.withpath"
value="${jdom.home}/build/${jdom.jar}"/>
etc...
</project>
Or, you can use a properties file:
<project name="sample" default="compile" basedir=".">
<property file="sample.properties"/>
etc...
</project>
And in sample.properties :
dir.build=build
dir.src=src
jdom.home=../java-tools/jdom-b8
jdom.jar=jdom.jar
jdom.jar.withpath=${jdom.home}/build/${jdom.jar}
Having a separate file for properties is beneficial because it explicitly defines the configurable portion of the build. You can provide a different version of this properties file for different platforms, or for developers working on different operating systems.
10. Keep the Build Process Self-Contained
To the greatest extent possible, do not refer to external paths and
libraries. Above all, do not rely on the programmer's CLASSPATH
setting. Instead, use relative paths throughout your buildfile
and define your own paths. If you refer to an explicit path such as
C:\java\tools
, other developers will not be able to use your
buildfile because they are highly unlikely to use the same
directory structure.
If you are deploying an open source project, provide a distribution that includes all JAR files necessary to compile your code, subject to licensing restrictions, of course. For internal projects, dependent JAR files should be managed under version control and checked out to a well-known location.
When you do have to refer to external paths, define the paths as properties. This lets programmers override those settings to conform to their own machines. You can also refer to environment variables using this syntax:
<property environment="env"/>
<property name="dir.jboss" value="${env.JBOSS_HOME}"/>
<!-- <csperl file="set_book_cover_image"> --> <!-- sidebar begins -->
Related Reading <!-- <csif perl="$cfg->vars('cover_image_url_base')"> --> <!-- <csperl>print $cfg->vars('cover_image_url_cat');</csperl> --> <!-- </csif> -->Ant: The
Definitive Guide
<!-- builds links to list in sidebar -->
<!-- csperl>
my @links = split(/(?:\r?\n)+/, ( $DATA{"supporting_links"} || "" ));
for my $link ( @links ) {
my ( $name, $url ) = split /=/, $link, 2;
next unless $name and $url;
$url = "http://oreilly.com/catalog/$DATA{'reference'}/$url" unless $url =~ /^\w+:/os;
$url = $url . "?CMP=ILL-4GV796923290";
if ($name =~ /Table of Contents/) {
print qq~ <a href="$url">$name</a><br /> \n ~;
} elsif ($name =~ /Index/) {
print qq~ <a href="$url">$name</a><br /> \n ~;
} elsif ($name eq "Author's Article") {
print qq~ <a href="$url">$name</a><br /> \n ~;
} elsif ($name =~ /Sample Chapter/) {
print qq~ <a href="$url">$name</a><br /> \n ~;
} else {
print qq~\n~;
}
}
</csperl-->
|
<!-- sidebar ends -->
11. Use Version Control
The buildfile is an important artifact that should be versioned, just like source code. When you tag or label your code, apply the same tag or label to your buildfile. This lets you go back to a previous release and build the software using the buildfile as it was back then.
In addition to the buildfile, you should maintain third-party JAR files in version control. Again, this makes it possible to recreate previous releases of your software. This also makes it easier to ensure that all developers have the same JAR files, because they can check them out of version control to a path relative to the buildfile.
Generally, avoid storing build output in version control. Provided that your source code is versioned properly, you should be able to recreate any previous release through the build process.
12. Use Ant as the Least Common Denominator
Suppose your team uses an IDE. Why bother with Ant when programmers can click the lightning bolt icon to rebuild the whole application?
The problem with IDEs is one of consistency and reproducibility across a team of members. IDEs are almost always designed for individual programmer productivity, not for consistent builds across a team of developers. Typical IDEs require each programmer to define his or her own project file. Programmers may have different directory structures, may use different versions of various libraries, or may be working on different platforms. This leads to situations where code that compiles fine for Bob may not build properly for Sally.
Regardless of what IDE your team uses, set up an Ant buildfile that all programmers use. Make a rule that programmers perform an Ant build before checking new code into version control. This ensures that code is always built from the same Ant buildfile. When problems arise, perform a clean build using the project-standard Ant buildfile, not someone's particular IDE.
Programmers should be free to use whatever IDE or editor they are comfortable with. Use Ant as a common baseline to ensure the code is always buildable.
13. Use zipfileset
People often use Ant to create WAR, JAR, ZIP, and EAR files. These files generally require a particular internal directory structure, one that usually does not match the directory structure of your source code and build environment.
An extremely common practice is to write an Ant target that copies
a bunch of files to a temporary holding area using the desired
directory structure, and then create the archive from there. This
is not the most efficient approach. Using a zipfileset
is a
better solution. This lets you select files from any location
and place them in the archive file using a different directory
structure. Here is a small example:
<ear earfile="${dir.dist.server}/payroll.ear"
appxml="${dir.resources}/application.xml">
<fileset dir="${dir.build}" includes="commonServer.jar"/>
<fileset dir="${dir.build}">
<include name="payroll-ejb.jar"/>
</fileset>
<zipfileset dir="${dir.build}" prefix="lib">
<include name="hr.jar"/>
<include name="billing.jar"/>
</zipfileset>
<fileset dir=".">
<include name="lib/jdom.jar"/>
<include name="lib/log4j.jar"/>
<include name="lib/ojdbc14.jar"/>
</fileset>
<zipfileset dir="${dir.generated.src}" prefix="META-INF">
<include name="jboss-app.xml"/>
</zipfileset</ear>
In this example, all JAR files are placed in the lib
directory of
the EAR. The hr.jar
and billing.jar
files are copied
from our
build directory, therefore we use zipfileset
to move them
to the
lib
directory inside of the EAR. The prefix attribute specifies
the destination directory in the EAR.
14. Perform the Clean Build Test
Assuming your buildfile has clean
and compile
targets, perform
the following test. First, type ant clean
. Second,
type ant compile
. Third, type ant compile
again. The third step should
do absolutely nothing. If files compile a second time, something is
wrong with your buildfile.
A buildfile should perform work only when input files change with respect to corresponding output files. A build process that compiles, copies, or performs some other work when it is not necessary to perform the work is inefficient. Even small inefficiencies become big problems when a project grows in size.
15. Avoid Platform-Specific Ant Wrappers
For whatever reason, some people like to ship their products with simple batch files or scripts called something like compile . Look inside of the script and you will find the following:
ant compile
Developers are familiar with Ant and are perfectly capable of
typing ant compile
. Do not include a
platform-specific script
that does nothing but invoke Ant. Your script becomes one more
little annoyance for people to study and understand when they are
looking at your tool for the first time. It is also likely that
you will fail to provide scripts for every operating system out
there, which will really annoy some users.
Summary
Too many companies rely on manual processes and ad hoc procedures for compiling code and creating software distributions. Teams that do not use a defined build process with Ant or similar tools spend an amazing amount of time tracking down problems when code compiles for some developers but fails for others.
Creating and maintaining build scripts is not glamorous work, but is necessary. A well-crafted Ant buildfile lets you focus on what you enjoy most -- writing code!
References
- Ant
- AntGraph : A tool for visualizing Ant dependencies
- Ant: The Definitive Guide , O'Reilly
- Java Extreme Programming Cookbook , O'Reilly
Eric M. Burke is an O'Reilly author and a principal software engineer with Object Computing, Inc. in St. Louis, MO.
O'Reilly & Associates published Java Extreme Programming Cookbook in March 2003.
-
Chapter 4, "JUnit," is available free online.
-
You can also look at the Table of Contents , the Index , and the full description of the book.
-
For more information, or to order the book, click here .
Return to ONJava.com .
<!-- end article content --> <!-- OST promo --> <!-- end O'Reilly Learning box --> <!-- end content -->
You must be logged in to the O'Reilly Network to post a talkback. <!-- thread_header.view --> <!-- end .tb_right --> <!-- this div is causing a problem on dm --> <!-- <div class="clear"></div> --> <!-- closing divs from a/print.view, et al -->
Showing messages 1 through 24 of 24.
-
Are you high?!
2007-05-16 12:45:08 <!-- begin conditional display of username --> mleejr <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Best practices?! Really? Section 10 talks about using OS LEVEL ENVIRONMENT VARIABLES for your tool paths?! ARE YOU KIDDING ME?! It makes it a lot easier to just have a directory full of your tools and point to them with a variable in ant. That way, if a new guy comes along, he can just copy the directory structure and be up and running. And, if anyone wants to, they can EDIT THEIR BUILD PROPERTIES FILE LIKE THEY SHOULD! That's the place to make it system agnostic. That's why you typically have a build.dev.properties, build.qa.properties, etc. So if I include Jmeter and tomcat in my builds, rather than have a 'jmeter.home="/java/jmeter"' and a 'tomcat.home="/java/tomcat"' and then set 'tomcat.home="/otherdir/tomcat"' in your build.personal.properties if you want to change it, you now have to set it in Control Panel->System->Advanced->Environment Variables...really? That's your suggestion?
-
How to share a database connection betwwen
differnet ant (sql) task
2007-01-10 03:39:42 <!-- begin conditional display of username --> Ashishindore <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]I am using ANT for deployment of my product.I need to run different SQL's at different stages of my deployment, so if i use ANT SQL task it will create a new DB connection each time.Is there any way i can share the DB connection between different tasks.(may be putting the connection in Project class thru my custom SQL task....)?
Thanks in Advance
Ashish
-
Deploy
2006-12-12 21:07:17 <!-- begin conditional display of username --> quangtn <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Could you tell me the way to deploy source from windows to linux server via SSH?
-
See also best practices appendix in Manning book
2005-04-26 11:04:56 <!-- begin conditional display of username --> aronr <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]This article, which is excellent, covers some of the same ground as Appendix D, The elements of Ant style, in Erik Hatcher and Steve Loughran's excellent book, Java Development with Ant, from Manning Publications:
http://www.manning.com/hatcher
That appendix provides 57 (!) best practices tips, organized into six sections.
-
Best practices I follow
2005-04-18 06:35:23 <!-- begin conditional display of username --> chinmayas <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Say I have few modules common, ejb1, webapp1, ear
I would create build file as follows
<project name="project1" default="build" basedir=".">
<target name="init">
read props file
init all the properties like dir, jar names
</target>
<target name="common" depends="init,compile_common,jar_common">
<target name="compile_common" depends="init">
compile common code
</target>
<target name="jar_common" depends="init">
jar common code
</target>
<target name="ejb1" depends="init,common,compile_ejb1,jar_ejb1">
<target name="compile_ejb1" depends="init">
compile ejb1 code
run appc
</target>
<target name="jar_ejb1" depends="init">
jar ejb1 code
</target>
<target name="webapp1" depends="init,common,ejb1,compile_webapp1,war_webapp1">
<target name="compile_webapp1" depends="init">
compile webapp1 code
run jspc
</target>
<target name="war_webapp1" depends="init">
create webapp war
</target>
<target name="ear_app" depends="init,common,ejb1,webapp1,ear_only">
build ear - executed all dependencies
</target>
<target name="ear_only" depends="init">
build only ear
</target>
<target name="build" depends="init,common,ejb1,webapp1,ear_app">
build all
</target>
<target name="deploy" depends="init,build,deploy_only">
run dependencies and deploy
</target>
<target name="deploy_only" depends="init">
deploy to server
</target>
<target name="undeploy" depends="init">
undeploy ear
</target>
<target name="clean" depends="init">
delete build, classes, generated dirs
</target>
</project>
To just build
$ ant
To build and deploy
$ ant deploy
If modifying common and want to deploy
add following one-liner target
<target name="common_deploy" depends="init,common,ear_only,deploy_only"/>
now run
$ ant common_deploy
similarly you can have war_deploy, ejb1_deploy etc.
Having fine grained targets helps to compose utility targets like above. These
improves the productivity of the developers. Developer do not have to wait for the
whole product/project to build, just compile changed module and re-jar it and deploy.
Note: In the above build file, you might notice in 'build' target is calling common,
ejb1, webapp1 and ear_app. And ear_app is also calling common, ejb1, webapp1 - this is
not going to call these targets twice. Ant does not call the dependency target twice.
regards
chinmaya
-
number 14: how?
2005-04-08 08:47:03 <!-- begin conditional display of username --> mhorowitz <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]The ant build system I work with most of the time is constantly rebuilding things. Is there an easy way to avoid this? <uptodate> gets evaluated before any of the targets, which means that something later in the build can appear up to date when it's not. I can use a <mapper> with an <apply> task, but not with a <java> task. This is going to be a controversial comment, but one thing make sure gets better than ant is declaring what files are inputs and outputs of a rule.
-
Extension of ANTGRAPH
2004-11-17 01:10:32 <!-- begin conditional display of username --> Roock <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]I found the best practices and the ANTGRAPH tool very useful. I have extended the XSL file of ANTGRAPH to parse the <ant ...> tag also:
<?xml version="1.0" encoding="UTF-8"?>
<!--
- An XSLT stylesheet that converts an Ant buildfile into a Graphviz/Dot
- input file.
- @author Eric M. Burke
- @version $Id: antgraph.xslt,v 1.3 2003/07/19 02:23:23 Eric Exp $
-
- Stefan Roock, 2004-09-17: parse <ant...> also
-->
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:text>digraph G {
</xsl:text>
<xsl:apply-templates select="project/target"/>
<xsl:apply-templates select="project/target//antcall"/>
<xsl:apply-templates select="project/target//ant"/>
<xsl:text>}
</xsl:text>
</xsl:template>
<!-- show antcall tasks with dotted lines -->
<xsl:template match="antcall">
<xsl:text> "</xsl:text>
<xsl:value-of select="ancestor::target/@name"/>
<xsl:text>" -> "</xsl:text>
<xsl:value-of select="@target"/>
<xsl:text>" [style=dotted];
</xsl:text>
</xsl:template>
<!-- show ant file tasks with dotted lines -->
<xsl:template match="ant">
<xsl:text> "</xsl:text>
<xsl:value-of select="@antfile"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="@target"/>
<xsl:text>" [shape=box];
</xsl:text>
<xsl:text> "</xsl:text>
<xsl:value-of select="ancestor::target/@name"/>
<xsl:text>" -> "</xsl:text>
<xsl:value-of select="@antfile"/>
<xsl:text>:</xsl:text>
<xsl:value-of select="@target"/>
<xsl:text>" [style=dotted];
</xsl:text>
</xsl:template>
<xsl:template match="target">
<xsl:choose>
<xsl:when test="@depends">
<xsl:call-template name="parseDepends">
<xsl:with-param name="target_order" select="1"/>
<xsl:with-param name="depends_from" select="@name"/>
<xsl:with-param name="depends_to" select="@depends"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- this target has no dependencies -->
<xsl:text> "</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>";
</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="parseDepends">
<xsl:param name="target_order"/>
<xsl:param name="depends_from"/>
<xsl:param name="depends_to"/>
<xsl:variable name="firstToken">
<xsl:choose>
<xsl:when test="contains($depends_to, ',')">
<xsl:value-of select="normalize-space(substring-before($depends_to,','))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="normalize-space($depends_to)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="remainingTokens"
select="normalize-space(substring-after($depends_to,','))"/>
<xsl:text> "</xsl:text>
<xsl:value-of select="$depends_from"/>
<xsl:text>" -> "</xsl:text>
<xsl:value-of select="$firstToken"/>
<xsl:text>"</xsl:text>
<!-- show the target_order -->
<xsl:if test="($target_order > 1) or (contains($depends_to, ','))">
<xsl:text> [label="</xsl:text>
<xsl:value-of select="$target_order"/>
<xsl:text>"]</xsl:text>
</xsl:if>
<xsl:text>;
</xsl:text>
<xsl:if test="$remainingTokens">
<xsl:call-template name="parseDepends">
<xsl:with-param name="target_order" select="$target_order+1"/>
<xsl:with-param name="depends_from" select="$depends_from"/>
<xsl:with-param name="depends_to" select="$remainingTokens"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
-
Put Ant in Version Control too!
2004-01-03 20:26:54 <!-- begin conditional display of username --> David Bock | <!-- 0 --> <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]The article almost implied it, but it is worth saying explicitly. The version of Ant you are using for your project should go into your version control repository as well.
While the article discouraged 'wrapper' build scripts, they serve a useful purpose when you have Ant in version control with your project - you can have a build file that searches the proejct tree for the Ant install to use, then you can have different versions of Ant across different projects. when Ant is installed on your machine, it is both outside of source control, and a dependency that can be difficult to manage across multiple projects.-
Put Ant in Version Control too!
2004-04-19 05:26:26 <!-- begin conditional display of username --> wrschneider99 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]you can have a build file that searches the proejct tree for the Ant install to use, then you can have different versions of Ant across different projects.
I've found it useful to have a wrapper script that sets environment variables (ANT_HOME, CLASSPATH and JAVA_HOME) and then invokes $ANT_HOME/bin/ant. This is essential for an internal development environment where some projects depend on JDK 1.4, some still depend on 1.3, and people switch between projects often. Whatever happens to be in the user's JAVA_HOME at the current moment may not be the right one, and using the wrong JDK may produce very subtle and hard-to-understand errors at runtime.
-
Put Ant in Version Control too!
-
Crisp and poster-perfect
2004-01-03 06:14:42 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Very well written. This is an article every manager should give to his/her development team before starting any Java project.
-
JAR files under version control and clean build
test
2003-12-20 04:05:34 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]I agree with all of our practices, we are using ant exactly this may!
however the idea of "dependent JAR files should be managed under version control" (10) may lead to:
<target name="compile" depends="init,externaljars">
<javac srcdir="${src}" destdir="${builddir}">
<classpath>
<pathelement location="${builddir}/>
<pathelement location="${externallibs}/servlet.jar"/>
..
</classpath>
</javac>
</target>
<target name="externaljars">
<cvs package="${externallibs}/servlet.jar"/>
...
</target>
ant will recompile everything, everytime, because whenever the external "servlet.jar" is checked out from version control, the compile targets dependencies have changed. This is in contrast to (14) "Clean Build Test".
-
The easiest way to implement a "clean" target...
2003-12-19 02:29:44 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]... is to produce all of your output (classes, tests...) in a new "build" directory. This way you can just delete this directory to implement your clean target.
To the most extent, you would copy your sources in it, then compile them here, just to make consistent "dist" target if you want to distribute the sources also...
I've seen horrible things in some "clean" targets where the guy tries to identifies all of its project output (some classes here, other there...), while it is so easy to centralise all in a single specific directory, like this for instance :
root
+- src
+- srcTest
+- rsc
+- ant.output <- your output dir !
+- src
+- srcTest
+- src.classes (maybe resources have been copied inside...)
+- srcTest.classes
+- testOutput
+- lib
+- dist
And voila the clean target : <delete dir="ant.output"/>
Just my personal best practice :)
-
The easiest way to implement a "clean" target...
2003-12-19 02:31:49 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]wow, my display has been trimed, but all below "ant.output" should be indented, you get the idea...
-
The easiest way to implement a "clean" target...
-
RE: Maven
2003-12-18 15:59:55 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Before you go running off to maven, read this: http://www.jroller.com/page/fate/20031002#to_celebrate_the_tss_thread-
RE: Maven
2004-03-11 23:53:11 <!-- begin conditional display of username --> andre-z <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]So, I've been there , what useful I was supposed to find? Much more information I got from Me and my Ant
-
RE: Maven
-
have you consider jakarta's maven build tool?
2003-12-18 11:04:26 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]My comment while not particularly relevant to the article, offers an alternative to using ANT and customizing its tasks for a given project. jakarta's MAVEN
builds ears, wars, jars, documented websites, cactus /junit tests, xdoclet driven files, etc. without the developer having to be bothered w/ programming build processes in addition to an application.
I highly encourage all java developers to consider switching to Maven for your build needs. It also supports ant tasks if find Maven doesnt offer desired tasks. You wont be disappointed.
-
have you consider jakarta's maven build tool?
2003-12-18 13:00:43 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Here, here!!
After spending years building custom ant scripts for dependency management, etc, I was thrilled to find Maven. It's got some rough edges, but out of the box it does a ton more than ant ever did and is much more extensible (easily at least).
You can even change the value of a property once you've defined it! :)
-
have you consider jakarta's maven build tool?
-
Tip 9 should use location attribute
2003-12-18 09:57:37 <!-- begin conditional display of username --> myshkin5 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]When specifying file or directories in properties it's a good idea to use the location attribute instead of the value attribute seen in tip 9. The location attribute causes ant to find the file or directory specified (if it exists) and pass a full platform-specific canonical path to the task. This is especially important when forking tasks start in a different directory.
-
More properties tips
2003-12-18 07:54:39 <!-- begin conditional display of username --> jimothy <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]I use a system of two properties files:
my.build.properties
build.properties
my.build.properties takes precedence over build.properties, allowing team members to override properties with machine specific values. This is where you'd put your absolute paths, such as the location of Tomcat/WebLogic/etc.
Towards the top of the Ant script, include:
<property file="my.build.properties"/>
<property file="build.properties"/>
<property file="${user.home}/build.properties"/>
Also be sure to include my.build.properties in your .cvsignore file so team members don't accidentally check in the file and overwrite your own properties.
-
More properties tips
2005-04-15 06:08:34 <!-- begin conditional display of username --> joachimm <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]We do build.${user}.properties so that each
developer can have their own project-specific
version checked into CVS.
And shouldn't ${user.home}/build.properties
be before build.properties?
-
More properties tips
-
Antdoc
2003-12-18 01:56:37 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]Very usefull along the lines of your javadoc is Antdoc http://antdoc.free.fr/. When using this use the target description as often as possible, also put a comment before targets with any extra information.
<!-- target infomation -->
<target/>
-
why have compile.bat?
2003-12-17 18:26:20 <!-- begin conditional display of username --> acroyear <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]and other common shortcuts for that matter?
convenience. in a GUI world, switching from the mouse to the keyboard and back again sucks. as does making a user have to look up (via ant -projecthelp) the actual build instruction when there can be several depending on the size of the distribution.
So having a few .bat files for the most common tasks that a non-developer would have, like having a quick "installme" script that would do "./configure; make; make install" with most autoconf-driven packages, can make things easier for users who just need the stuff without needing to know why it works or how to make it work in detail. somedays i just want the .jar, and i don't really want to dig into the buildfile to figure out what to call to get it.-
why have compile.bat?
2003-12-18 14:39:00 <!-- begin conditional display of username --> anonymous2 <!-- end conditional display of username --> <!-- csif cond="1" --> [Reply | View ]In a GUI world, wouldn't you have a GUI window just for Ant build files that shows you all the targets and that gives you a way to specify parameters and such like?
I'm talking about something like IntelliJ IDEA's Ant support, of course.
-
why have compile.bat?
<!-- end noindex -->
相关推荐
### Rational Unified Process (RUP) 最佳实践 #### 什么是Rational Unified Process (RUP)? Rational Unified Process(简称RUP)是一种软件工程过程,它为软件开发团队提供了一个结构化的方法来指导整个软件开发...
Vue.js Design Patterns and Best Practices Vue.js Design Patterns and Best Practices
Chapter 9: Best Practices for Function-Based Views Chapter 10: Best Practices for Class-Based Views Chapter 11: Form Fundamentals Chapter 12: Common Patterns for Forms Chapter 13: Templates: Best ...
NHTSA_Cybersecurity Best Practices for Modern Vehicles
Best Practices packages are currently available: 1. SAP Best Practices for SAP S/4HANA - This package provides preconfigured processes and content specifically designed for the SAP S/4HANA platform. ...
java database best practices
To gain these benefits, however, team members need common troubleshooting skills and practices.In DevOps Troubleshooting: Linux Server Best Practices, award-winning Linux expert Kyle Rankin brings ...
#### 标题解读:“Oracle APEX Best Practices” 该标题明确指出本文档将介绍在使用 Oracle APEX 进行开发时应遵循的最佳实践。对于那些希望提高 Oracle APEX 应用程序质量和性能的开发者来说,这是一个非常宝贵的...
High Performance Spark Best Practices for Scaling and Optimizing Apache Spark 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn删除
android-database-best-practices android-database-best-practices android-database-best-practices android-database-best-practices android-database-best-practices
React Design Patterns and Best Practices 英文mobi 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
React Design Patterns and Best Practices 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
Perl Best Practices author Damian Conway explains that rules, conventions, standards, and practices not only help programmers communicate and coordinate with one another, they also provide a reliable...
Java Enterprise Best PracticesJava Enterprise Best Practices
Django Design Patterns and Best Practices 英文mobi 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
Data Visualization — Best Practices and Foundations.pdf Data Visualization — Best Practices and Foundations.pdf
Practical Web Scraping for Data Science Best Practices and Examples with Python 英文epub 本资源转载自网络,如有侵权,请联系上传者或csdn删除 查看此书详细信息请在美国亚马逊官网搜索此书
《Pro .NET Best Practices》是一本深入探讨.NET开发最佳实践的专业书籍。这本书旨在帮助开发者们提升他们的编程技能,遵循高效、可维护、可扩展的代码编写标准,从而提高软件项目的质量和生产效率。以下是对该书...