Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2336744
  • 博文数量: 527
  • 博客积分: 10343
  • 博客等级: 上将
  • 技术积分: 5565
  • 用 户 组: 普通用户
  • 注册时间: 2005-07-26 23:05
文章分类

全部博文(527)

文章存档

2014年(4)

2012年(13)

2011年(19)

2010年(91)

2009年(136)

2008年(142)

2007年(80)

2006年(29)

2005年(13)

我的朋友

分类: WINDOWS

2007-10-24 11:51:35

自己用nant 的过程中发现的一些几乎有用的小片断, 不好意思学人家叫cookbook, 还没到那个规模

基于NAnt 0.85 (Build 0.85.2478.0; release; 2006-10-14)

1. 取当前日期时间: 内置task: tstamp
   time stamp的缩写

<tstamp property="curr_time" pattern="yyyy-MM-dd HH:mm:ss" verbose="false"/>
<echo message="${curr_time}" />


   [tstamp] 2007年10月24日 11:25:16.
     [echo] 2007-10-24 11:25:16

[tstamp] 那一行有时候会变得很讨厌, 但没办法关闭, 你也许已经看到我企图用verbose="false"来关闭它, 但没用.

pattern中的大小写是敏感的, 我想上面给出的格式在绝大多数情况下就都足够用了, 精确到了秒.

对于只是想提供日期时间信息, 但不在乎格式, 又不想记这些pattern怎么写的人, 可以简单地用

<tstamp />
<echo message="${
tstamp.now} | ${tstamp.date} | ${tstamp.time}" />


但是, 它的输出往往对中国人是不友好的, 我们不习惯 "月/日/年"这样的表达法, 面对 03/05/2007 总是会怀疑究竟是3月5号, 还是5月3号. 所以, 我对同胞们的建议是: 不要用这三个变量的值显示给不管是你自己还是你的同事看.

每一次执行一个tstamp 任务, 它会设置上面的3个变量, 注意这三个变量并非是每次取用的时候就自动是当前的日期/时间值, 必需对它进行设置. 这不是.NET中的 DateTime.Now 属性.

个人认为在启动一个nant任务时默认地给这三个变量赋值是比较合适的做法, 但目前的nant 不是这样做的, 从未执行一次任务就去使用这三个变量会导致变量未赋值的错误:

Expression: ${tstamp.now} | ${tstamp.date} | ${tstamp.time}
              ^^^^^^^^^^
    Property 'tstamp.now' has not been set.


注意并非为了设置这三个变量就得运行一个 这样的最简形式, 设置这三个变量的值是只要运行该任务就一定会有的副作用.

2. 显示信息: echo 内置任务

nant中的echo 就是 C中的printf, 它几乎是每个人都会用/都想用, 甚至也是用的最多的调试手段. 最简单的形式:

<echo message="Hello, world"/>

既使它如此简单, 我相信下面的内容还是绝对你一看:

2.1 在XML的属性中换行:

<echo message="Hello world"/>

是XML的Entity, 十进制, 表示换行, 就是你在C字符串中的\n

2.2 输出大块文本

<echo>

Hello, world

The time is, ${tstamp.now}

]]>



是XML有意定义的怪兽, 目的就是尽可能的奇怪, 以致于你基本不可能在有意义的文本中用到. 它里面可以放大块大块的内容, 而且可以含有 <> 这样的在普通XML文本和XML属性中被禁止使用的值.

但是, 我认为nant还是对XML的这种机制进行了有意的违背: 它允许使用变量内插, 就是上面的${tstamp.now}, 类似于bash 中的  < ...
END
和perl中双引号中允许内插变量值一样. 这个十分方便, 否则你就得不停地在
2.3 用if 控制是否输出

不管是程序代码还是 nant脚本, 如果有一次你需要这样的输出来帮助调试, 那么很大的机会你以后还会要, 所以即使调试完之后也不要把printf/echo 删除, 而是把它留在代码里, 用一个开关随时切换.
C/C++可以用
#if 0
#endif

C#必需用 #if false, 它不支持#if 0

对于几乎所有的nant 任务, 都可以指定一个if 属性来通过条件控制是否执行, 简单地禁用需要这样:
if="false"

2.4 用 file="filename.txt" 和 append="true" 控制向文件写入

写入的内容不再是到标准输出, 而是重定向到了指定的文件.

3. 执行外部命令: exec 内置任务

执行外部命令非常常用, 即使是nant内置了cvs/mail这样的任务, 但并不是每个任务都能很好地工作, 所以我实际上是用cvs.exe 命令来取代码, 用perl脚本来发邮件:

<exec program="nant.exe"
      commandline="-buildfile:Build.Build -l:${log_file} ${build_target}"
      workingdir="${build_dir}/MyProject/src" output="output.txt"
      failonerror="false" resultproperty="build_result" />


program 是必需的, 注意只在这里写可执行文件名, 不要写参数, nant会认为整个program属性的内容都是
可执行文件的名字, 不必是绝对路径, 只要在%PATH%变量中可以找到即可, 目录名/文件名中也可以含有空格.

commandline也几乎是必需的, 所有的参数都一古脑写在这里, 不要用什么单独的arg标签.

workingdir 有时候对命令的正确执行至关重要, 比如上面的cvs命令, 它就关乎着取出的代码放在哪个目录下.

failonerror 和 resultproperty 两个往往一起使用, resultproperty 的返回值就是C里面exit( code ); 的参数值. 代表进程的退出状态, 一般的约定是0为正常, 其它值有错误.

注意接下来取用 resultproperty 值的时候它却被当作是一个字符串, 因此你不能用这样的条件来进行判断:
if = "${ resultproperty == 0}"
而必需是
if = "${ resultproperty == '0'}"

output属性把命令执行的结果同时存为指定的文件, 注意同时标准输出上还是会显示命令的输出, 包括标准输出和标准错误输出, 没有简单的办法来禁止向标准输出写东西, 下面是一个可行但不那么优雅的方案

这个命令行不通过 output来指定输出文件, 而是通过 commandline, 在里面指定 > tmp.txt进行重定向, 注意需要用> 来代替>符号, 这是XML!

也许你注意到了, echo 用file表示输出文件, 而这里用 output, 是的, 我也讨厌这样的不一致.

4. 显示所有可调用的target

不象makefile, 你没有简单的办法列出所有可以作为目标的名称,
nant -f:file.build -projecthelp
会显示所有的target

5. 退出脚本执行: fail内置任务

有时候为了调试时跳过一段耗时太长的脚本, 你希望有一个C语言中exit(1)一样的功能, 在nant中是 fail内置任务, 因为nant默认的规则是碰到错误就退出, 所以你强制一个错误发生就相当于让它退出. 不同的是你无法指定一个退出码, fail一定会被外部的程序视为错误, nant返回时 %errorlevel%的值是1

6. property 值是全局变量

注意所有调用的property 属性都是全局性质的, 不管你是通过 call, 还是因为 依赖关系调用的, 一经设置, 一直生效.

7. 判断存在性

if="${property::exists('var_name')}"
if="${file::exists('filename')}"
if="${directory::exists('dirname')}"
这个exists 名字起的还算统一


8. 如果涉及路径名/文件名, 一概用绝对路径.

跟shell脚本的惯例一样, 这样参避免很多问题.

9. 如果涉及property 这样的可变值, 在脚本头部, 尽可能集中地一次性设置好.

这样你改起来方便. 也符合软件工程里把变化的部分和不变的部分分开管理的原则.
阅读(1026) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~