第 2 章 Build Tools

简介:

2.1. Apache Ant

http://ant.apache.org/

2.1.1. 安装 ant

2.1.1.1. 1.8

cd /usr/local/src
wget http://mirror.bjtu.edu.cn/apache//ant/binaries/apache-ant-1.8.1-bin.tar.gz
tar zxvf apache-ant-1.8.1-bin.tar.gz
mv apache-ant-1.8.1 /usr/local/
cd ..
ln -s apache-ant-1.8.1 apache-ant
			
ANT_HOME=/usr/local/apache-ant
export CLASSPATH=$CLASSPATH:$ANT_HOME/lib
			

2.1.1.2. 1.10.1

Netkiller OSCM 一键安装

curl -s https://raw.githubusercontent.com/oscm/shell/master/lang/java/ant/apache-ant-1.10.1.sh | bash
			

2.1.2. ANT

2.1.2.1. ant.project.name

ant.project.name 一般式定义在

			
<project name="www.netkiller.cn" default="compile" basedir="." xmlns:if="ant:if">
<echo>${ant.project.name}</echo>
			
			

我们希望从命令行传递这个值

			
<project default="compile" basedir="." xmlns:if="ant:if">
<echo>${ant.project.name}</echo>
			
			

你需要将 project 中的定义去掉才能从命令行传递

			
ant -Dant.project.name=www.netkiller.cn -f build.xml
			
			

你也可以从 build.properties 文件定义 ant.project.name

			
MacBook-Pro:deployment neo$ cat build.properties 
ant.project.name=www.netkiller.cn			
			
			
			
ant -f build.xml -propertyfile build.properties	
			
			

2.1.2.2. 定义

			
			
			

2.1.3. Project

		
<description>project Name</description>
		
		

2.1.3.1. property

在 build.xml 中定义 property

			
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<property name="hello" value="hello.jar"/>		
			
			

引用 properties 文件

			
<property file="build.properties" />
<propety resource="build.properties"/>
			
			

设置系统的环境变量为前缀

			
<property environment="env"/> 
<property name="tomcat.home" value="${env.CATALINA_HOME}"/> 
			
			

命令行传值,使用-D参数是会覆盖build.xml中的先前定义的变量

			
$ ant --help | grep property
  -D<property>=<value>   use value for given property
  -propertyfile <name>   load all properties from file with -D
  

	 		
			

2.1.3.2. ant

Project name

			
${ant.project.name}
			
			

2.1.3.3. environment

			
<property environment="env"/>
<echo message="JAVA_HOME is set to = ${env.JAVA_HOME}" />			
			
			

2.1.4. path

定义

		
	<path id="classpath">  
        <fileset dir="${env.JAVA_HOME}/lib">  
            <include name="*.jar" />  
        </fileset>  
        <fileset dir="${env.CATALINA_HOME}/lib">  
            <include name="*.jar" />  
        </fileset>  
        <fileset dir="WebRoot/WEB-INF/lib" includes="*.jar"/>
    </path>    
		
		

引用

		
	<javac srcdir="${src.dir}" destdir="${classes.dir}" source="1.5" target="1.5">  
		<classpath refid="classpath" />  
	</javac>		
		
		

		
    <classpath>
		<path refid="classpath"/>
    </classpath>		
		
		

2.1.5. copy

复制目录

		
	<copy todir="${basedir}/WebContent"> 
		<fileset dir="${basedir}/WebRoot" includes="**/*"/>
	</copy>	    
		
		

复制指定扩展名文件

		
	<copy todir="${dest}">  
		<fileset dir="${src}">  
			<include name="**/*.xml" />  
			<include name="**/*.properties" />  
		</fileset>
	</copy> 	
		
		

2.1.6. javac

		
	<path id="classpath">
		<fileset dir="${env.JAVA_HOME}/lib">
			<include name="*.jar" />
		</fileset>
		<fileset dir="${env.CATALINA_HOME}/lib">
			<include name="*.jar" />
		</fileset>
		<fileset dir="${project.dir}/WebRoot/WEB-INF/lib" includes="*.jar" />
	</path>

	<javac srcdir="${project.src}" destdir="${project.build}/WEB-INF/classes" debug="true" listfiles="true">
			<classpath refid="classpath" />
			<include name="**/*.java"/>
			<exclude name="**/*.xml"/>
			<exclude name="**/*.properties"/>
	</javac>
		
		

listfiles 显示编译文件列表

debug 显示调试信息,编译错误信息

2.1.7. condition

		
<?xml version="1.0"?>
<project name="test" default="doFoo" basedir=".">
  <property name="directory" value="/www/directory"/>

  <target name="doFoo" depends="dir.check" if="dir.exists">
    <echo>${directory} exists</echo>
  </target>

  <target name="doBar" depends="dir.check" unless="dir.exists">
    <echo>${directory} missing"</echo>
  </target>

  <target name="dir.check">
    <condition property="dir.exists">
      <available file="${directory}" type="dir"/>
    </condition>
  </target>
</project>		
		
		

2.1.8. exec

		
<project name="{{ name }}" default="help" basedir=".">
  
  <property name="username" value="{{ username }}"/>
  <property name="host" value="{{ host }}"/>
  <property name="dir" value="/srv/{{ path }}/"/>

  <tstamp>
    <format property="TODAY_UK" pattern="yyyyMMddhhmmss" locale="en,UK"/>
  </tstamp>

  <target name="help" description="show available commands" >
    <exec executable="ant" dir="." failonerror="true">
      <arg value="-p"/>
    </exec>
  </target>
  
  <target name="deploy-to" description="show where we are deploying to" >
    <echo>${username}@${host}:${dir}</echo>
  </target>

  <target name="deploy" description="deploy usng rsync" >
    <exec executable="rsync" dir="." failonerror="true">
      <arg value="-r"/>
      <arg value="."/>
      <arg value="${username}@${host}:${dir}"/>
      <arg value="--exclude-from=rsync.excludes"/>
      <arg value="-v"/>
    </exec>
  </target>

  <target name="deploy-test" description="test deploy usng rsync with the dry run flag set" >
    <exec executable="rsync" dir="." failonerror="true">
      <arg value="-r"/>
      <arg value="."/>
      <arg value="${username}@${host}:${dir}"/>
      <arg value="--exclude-from=rsync.excludes"/>
      <arg value="--dry-run"/>
      <arg value="-v"/>
    </exec>
  </target>

  <target name="backup" description="backup site" >
    <exec executable="scp" dir="." failonerror="true">
      <arg value="-r"/>
      <arg value="${username}@${host}:${dir}"/>
      <arg value="backups/${TODAY_UK}"/>
    </exec>
  </target>

</project>		
		
		

2.1.8.1. sshexec

			
<sshexec host="${remove}" keyfile="~/.ssh/id_rsa" command="/srv/apache-tomcat/bin/catalina.sh stop -force" />			
			
			

2.1.9. if

		
		
<if>
  <available file="my_directory" type="dir" />
  <then>
    <echo message="Directory exists" />
  </then>
  <else>
    <echo message="Directory does not exist" />
  </else>
</if>		
		
		
		

Ant 1.9.x 新增 xmlns:if="ant:if"

		
<project name="tryit"
 xmlns:if="ant:if"
 xmlns:unless="ant:unless"
>
 <exec executable="java">
   <arg line="-X" if:true="${showextendedparams}"/>
   <arg line="-version" unless:true="${showextendedparams}"/>
 </exec>
 <condition property="onmac">
   <os family="mac"/>
 </condition>
 <echo if:set="onmac">running on MacOS</echo>
 <echo unless:set="onmac">not running on MacOS</echo>
</project>


<!DOCTYPE project>
<project xmlns:if="ant:if" xmlns:unless="ant:unless">
  <property unless:set="property" name="property.is.set" value="false"/>
  <property if:set="property" name="property.is.set" value="true"/>
  <echo>${property.is.set}</echo>
</project>
		
		

2.1.10. macrodef

arg value 与 arg line

arg line 可以处理参数的空格, 而arg value则不能. arg line 可以处理空参数, arg value传递空参数会报错.

		
<exec executable = "sh" dir = "@{dir}">
	<arg line = "ls -l /var/log" />
</exec>


<exec executable = "ls" dir = "@{dir}">
	<arg value = "-l" />
	<arg value = "/var/log" />
</exec>
		
		
		
        <macrodef name="mvn">
                <attribute name="options" default="" />
                <attribute name="goal" default="" />
                <attribute name="phase" default=" " />
                <attribute name="dir" default="" />
                <element name="args" optional="false" />
                <sequential>
                        <exec executable="mvn" dir="@{dir}" >
                                <arg value="@{options}" />
                                <arg value="@{goal}" />
                                <arg value="@{phase}" />
                        </exec>
                </sequential>
        </macrodef>

<!-- 执行下面宏将会出错,你必须传递options,phase参数 -->
<mvn goal="package" dir="${project.dir}"/>
<!-- 将vale改为line后正常 -->
		<exec executable="mvn" dir="@{dir}" >
                                <arg line="@{options}" />
                                <arg line="@{goal}" />
                                <arg line="@{phase}" />
        </exec>
		
		
		

运行方式sequential为顺序执行, parallel为并行执行。

2.1.10.1. Git

			
<macrodef name = "git">
    <attribute name = "command" />
    <attribute name = "dir" default = "" />
    <element name = "args" optional = "true" />
    <sequential>
        <echo message = "git @{command}" />
        <exec executable = "git" dir = "@{dir}">
            <arg value = "@{command}" />
            <args/>
        </exec>
    </sequential>
</macrodef>
<macrodef name = "git-clone-pull">
    <attribute name = "repository" />
    <attribute name = "dest" />
    <sequential>
        <git command = "clone">
            <args>
                <arg value = "@{repository}" />
                <arg value = "@{dest}" />
            </args>
        </git>
        <git command = "pull" dir = "@{dest}" />
    </sequential>
</macrodef>
			
			
			
<git command = "clone">
    <args>
        <arg value = "git://github.com/280north/ojunit.git" />
        <arg value = "ojunit" />
    </args>
</git>

<git command = "pull" dir = "repository_path" />		

<git-clone-pull repository="git://github.com/280north/ojunit.git" dest="ojunit" />	
			
			

2.1.10.2. Rsync

			
			
	<macrodef name="rsync">
		<attribute name="option" default="auzv" />
		<attribute name="src" default="" />
		<attribute name="dest" default="" />
		<element name="args" optional="true" />
		<sequential>
			<exec executable="rsync">
				<arg value="@{option}" />
				<arg value="@{src}" />
				<arg value="@{dest}" />
				<args />
			</exec>
		</sequential>
	</macrodef>			
			
			
			
			
	<target name="deploy" depends="compile">
		<rsync option="-auzv" src="${project.dest}" dest="${remote}:${destination}">
			<args>
				<arg value="-P" />
			</args>
		</rsync>
	</target>			
			
			

2.1.10.3. SSH

			
	<macrodef name="ssh">
		<attribute name="host" />
		<attribute name="command" />
		<attribute name="keyfile" default="~/.ssh/id_rsa" />
		<element name="args" optional="true" />
		<sequential>
			<exec executable="ssh">
				<arg value="@{host}" />
				<!-- arg value="-i @{keyfile}" / -->
				<args />
				<arg value="@{command}" />
			</exec>
		</sequential>
	</macrodef>
			
			
			
	<target name="stop" depends="">
		<!-- ssh host="${remote}" command="/srv/apache-tomcat/bin/catalina.sh stop -force" keyfile="~/.ssh/id_rsa" / -->
		<ssh host="${remote}" command="/srv/apache-tomcat/bin/shutdown.sh" />
	</target>
	<target name="start" depends="">
		<ssh host="${remote}" command="/srv/apache-tomcat/bin/startup.sh" keyfile="~/.ssh/id_rsa" />
	</target>		
			
			

2.1.10.4. maven

			
        <macrodef name="mvn">
                <attribute name="options" default="" />
                <attribute name="goal" default="" />
                <attribute name="phase" default=" " />
                <attribute name="dir" default="" />
                <element name="args" optional="false" />
                <sequential>
                        <exec executable="mvn" dir="@{dir}" >
                                <arg line="@{options}" />
                                <arg value="@{goal}" />
                                <arg line="@{phase}" />
                        </exec>
                </sequential>
        </macrodef>			
			
			

2.1.11. Javascript

		

$ cat build.xml 
<project name="Attachments" default="print">
    <property name="numAttachments" value="20" />
    <target name="generate">
        <script language="javascript"><![CDATA[
            var list = '1';
            var limit = project.getProperty( "numAttachments" );
            for (var i=2;i<limit;i++)
            { 
                list = list + ',' + i;
            }
            project.setNewProperty("list", list);            
		print(list);
        ]] >
        </script>    
    </target>
</project>

		
		
		
$ ant generate
Buildfile: /www/testing/build.xml

generate:
   [script] 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19

BUILD SUCCESSFUL
Total time: 0 seconds
		
		

2.1.12. mail

https://ant.apache.org/manual/Tasks/mail.html

		
cp ~/.m2/repository/com/sun/mail/javax.mail/1.5.6/javax.mail-1.5.6.jar /srv/apache-ant-1.9.6/lib
cp /www/.m2/repository/com/sun/mail/javax.mail/1.5.6/javax.mail-1.5.6.jar /srv/apache-ant-1.10.1/lib/
		
		

Examples

		
<mail from="me"
      tolist="you"
      subject="Results of nightly build"
      files="build.log"/>
Sends an email from me to you with a subject of Results of nightly build and includes the contents of the file build.log in the body of the message.

<mail mailhost="smtp.myisp.com" mailport="1025" subject="Test build">
  <from address="config@myisp.com"/>
  <replyto address="me@myisp.com"/>
  <to address="all@xyz.com"/>
  <message>The ${buildname} nightly build has completed</message>
  <attachments>
    <fileset dir="dist">
      <include name="**/*.zip"/>
    </fileset>
  </attachments>
</mail>
		
		

2.1.13. basename

		
<basename property="jar.filename" file="${lib.jarfile}"/>
will set jar.filename to myjar.jar, if lib.jarfile is defined as either a full-path filename (eg., /usr/local/lib/myjar.jar), a relative-path filename (eg., lib/myjar.jar), or a simple filename (eg., myjar.jar).
<basename property="cmdname" file="D:/usr/local/foo.exe"
          suffix=".exe"/>
will set cmdname to foo.
<property environment="env"/>
<basename property="temp.dirname" file="${env.TEMP}"/>
			
		
		

2.1.14. FAQ

2.1.14.1. warning: 'includeantruntime' was not set, defaulting to build.sysclasspath=last; set to false for repeatable builds

includeantruntime="false"

			
<target name="compile" depends="init">
   <javac includeantruntime="false" srcdir="${src}" destdir="${dest}"/>
</target>
			
			

or

			
<property name="build.sysclasspath" value="last"/>
			
			

2.1.14.2. 调试 exec

将 executable="echo" 设置成 echo 是一种不错的调试手段

			
        <macrodef name="gulp">
                <attribute name="stage" default=""/>
                <attribute name="src" default=""/>
                <attribute name="dir" default="" />
                <sequential>
                        <exec vmlauncher="false" executable="echo" dir="@{dir}" osfamily="unix">
                                <arg line="--stage @{stage} --src @{src}"/>
                                <!-- arg value="stage @{stage}" / -->
                        </exec>
                </sequential>
        </macrodef>

        <target name="gulp">
                <gulp stage="${git.branch}" src="cn" dir="."/>
        </target>
			
			




原文出处:Netkiller 系列 手札
本文作者:陈景峯
转载请与作者联系,同时请务必标明文章原始出处和作者信息及本声明。

目录
相关文章
|
Java Android开发 程序员
build.gradle中buildTypes和productFlavors详解
用过AS的程序猿都知道build.gradle文件的作用,但我仍坚信还是有很多猿友不知道build.gradle文件中的一些代码的意思到底是什么? 这里来说下buildTypes和productFlavors的作用,顺便会说下其他一些配置。
1571 0
|
1月前
|
Java Maven
maven加入lib然后add as library
maven加入lib然后add as library
7 0
|
Android开发
【错误记录】Android Studio 编译报错 ( Installed Build Tools revision 31.0.0 is corrupted )
【错误记录】Android Studio 编译报错 ( Installed Build Tools revision 31.0.0 is corrupted )
669 0
【错误记录】Android Studio 编译报错 ( Installed Build Tools revision 31.0.0 is corrupted )
|
Android开发 开发工具 IDE
Android gradle问题解决: This app has been built with an incorrect configuration. Please configure your build for VectorDrawableCompat
1. 问题描述: Android Studio在运行模拟器某些机型或者真机某些机型的时候发生闪退。 错误如下: Java.lang.RuntimeException: Unable to start activity ComponentInfo{com.
2279 0
|
开发工具
Dex Loader] Failed to load D:\adt-bundle-windows-x86_64-20190307\sdk\build-tools\28.0.3\lib\dx.jar
Dex Loader] Failed to load D:\adt-bundle-windows-x86_64-20190307\sdk\build-tools\28.0.3\lib\dx.jar
83 0
|
Android开发
Migrate Project to Gradle? This project does not use the Gradle build system
Migrate Project to Gradle? This project does not use the Gradle build system
78 0
|
Python
【解决方案】解决CMake must be installed to build the following extensions: pyltp
【解决方案】解决CMake must be installed to build the following extensions: pyltp
141 0
|
开发工具 Android开发
eclipse Unable to build: the file dx.jar was not loaded from the SDK folder的解决办法
eclipse Unable to build: the file dx.jar was not loaded from the SDK folder的解决办法
89 0
dpkg-checkbuilddeps: error: Unmet build dependencies: build-essential:native
dpkg-checkbuilddeps: error: Unmet build dependencies: build-essential:native
648 0
|
JavaScript Java