build工具的主页在:http://www.dsource.org/projects/build
它以前叫 bud,所以这里混用 bud 和build,都指的同一个东西
build是D语言的编译工具,相当于C的make命令。
但它更简单且好用,因为它能处理 import 语句,自动载入依赖的文件。
看过本文后,基本上可以使用了。
如果你想用它的高级功能,当然还得花时间去研究它。
build 会涉及的文件有:
brf文件 (Build Response File) -- bud命令的参数文件
源文件的 Pragmas 指令
rdf文件 (Rule Definition File) -- 规则定义文件
mdf文件 (Macro Definition File) -- 宏定义文件
cfg文件 (Configuration File) -- 配置文件
pfl文件 (Profile File) -- 配置文件?
其中,brf文件里面写的就是一些build命令的参数,所以,先从参数开始。
先看几个简单参数,然后再说说brf文件,最后把其他参数简单的列一下。
[注:以下在Linux和dmd下测试过,没有测试win和gdc]
build命令的格式是:
build <sourcefile> [<switches> ] [<otherfiles> ]
sourcefile 一般是包括main函数的源文件
switches 上面列出的参数
otherfiles 链接库,object文件,宏定义文件等等其他文件(猜的:))
参数和源文件都没有顺序,可以任意排列 -- 喜欢把源文件放前面,编译参数放后面,因为编译参数经常改
Bud的常用参数之一:常规选项
-exec 编译成功后,运行它
-cleanup 在编译完成后,把生成的中间文件删除掉,比如 .o 文件
-full 编译所有的文件,即使没有修改也要编译一遍
-T<name> 指定目标的文件名
-od<path> 指定.o 等临时文件的输出目录
-silent 安静模式,不输出多余信息
-test 只是显示要调用的命令,不实际编译
-v build 和 dmd 都是调试模式
-V build 是调试模式,但dmd命令不是
-info 显示build命令的版本号等信息
-names 显示要编译的文件名
-uses[=fname] 输出交叉引用文件
如果不是bud的参数,会传递给dmd。比如可以指定 -op -L-l 参数 [注:猜的,不肯定]
命令参数如果是一个横线(-),表示启用,如果是两个横线(--),表明禁用。
比如: bud --cleanup -full
两个横线(--)一般和brf文件配合使用,表明要禁用brf文件中的某个编译参数
给个例子:a.d 和 b.d
module a;
import b;
import std.stdio;
void main(char[][] arg)
{
writef("in Module A: ");
writefln(arg);
print_b();
}
module b;
import std.stdio;
void print_b()
{
writefln("in Module B: b.d");
}
最简单的编译方法:
bud a.d
bud a # 可以不写 .d 后缀
注意,这里不需要指定 b.d,因为a.d中的import起了作用。
bud命令会自动处理。是不是很简单?
编译后让它运行:
bud a.d -exec
bud a.d -execXXX # 给个参数XXX
bud a.d -exec"XXX YYY" # 给2个参数XXX YYY ; 在bash下不能正确运行,不知道怎么处理
改个名字:
bud a.d -Ta.out # 文件名是:a.out ;在命令行下,生成不了a.out,不知道怎么处理;(
bud a.d -Ttest_{Target} # 文件名是:test_a
如果你不修改a.d或者b.d,多次运行上面的命令,会提示:
Files are up to date, no build required.
这个和make的原理一样,如果你想每次都编译,可以这么办:
bud a.d -full
如果看着那么多的.o文件不爽,就把它删掉:
bud a.d -clean # -clean 是-cleanup的别名
几个调试选项:
bud a.d -names # 显示要编译的文件名
bud a.d -test # 显示dmd和gcc的调用命令
bud .ad -uses=x # 生成交叉引用文件,默认文件名是a.use,这里指定为x
bud a.d -v # 除了bud的调试信息,还显示dmd编译器的调试信息
bud a.d -V # 只显示bud的调试信息
use文件:
[USES]
a.d <> /usr/local/src/phobos/std/stdio.d
a.d <> b.d
b.d <> /usr/local/src/phobos/std/stdio.d
[USEDBY]
/usr/local/src/phobos/std/stdio.d <> a.d
/usr/local/src/phobos/std/stdio.d <> b.d
b.d <> a.d
可以看到,有2个标签:[USES] 和[USEDBY]
[USES] 的含义是 A 文件使用了哪些文件
[USEDBY] 的含义是 哪些 文件 别 A文件 使用了
每行的文件名之间用 <> 分割
升序排列
Bud的常用参数之二:编译选项
[注:对编译器的术语不是很清楚,会有些表达不清楚。回头研究一下编译术语,再来修改这段】
编译过程一般是 a.d (源文件) -> a.o (object文件) -> a.exe (可执行文件),这里不讨论预处理等过程
object文件还可以编译成 静态链接库(liba.a) 或者 动态链接库(liba.so)
a.d 到 a.o 的过程叫编译 过程
a.o 到 a.exe 的过程叫 连接过程(link)
a.o 到 liba.a/so 的过程叫 lib过程 [注:实在不知道怎么翻译;( ]
bud 默认会把有main()或者Winmain()函数的源程序编译成可执行文件;
如果没有这两个函数,则会被编译成链接库文件(.a)
下面这些选项可以改变这些行为:
不知道怎么生成 .so的文件?
-obj 只是创建 object文件(.o),不进行link和lib操作,等同于同时加 -nolink -nolib
-link 即使源文件中没有main()函数,也强制进行连接。
main()函数一般在链接库中,而不在要编译的源代码中
-nolink 针对有main()函数的源文件:不进行link操作,只生成 .o 文件
-lib 针对有main()函数的源文件:不进行link操作,只生成 .a 文件
-nolib 针对没有main()函数的源文件:不进行lib操作,只生成 .o 文件
-allobj 不懂:(
-LIBOPT 指定要连接的参数
-LIBPATH 指定链接库的目录
-PP 指定除当前路径外的 其他源文件的搜索路径
举例吧:
#-obj:只生成.o 文件
bud a.d -obj # 会同时生成 a.o b.o
bud b.d -obj # 生成 b.o,不会生成 a.o ;)
#-link:强制连接
bud a.d -obj # 生成 a.o
bud b.d a.o # 生成 b 可执行文件
#-nolink:不链接
bud a.d -nolink # 生成 a.o
#-lib:生成 静态库
bud a.d -lib # 生成 a.a 为何不是liba.a?
#-nolib: 不生成 静态库
bud b.d -nolib # 生成 b.o ,而不是 b.a
LIZBOPT的作用不大清楚,把原文的定义列出来吧,偷懒了
-LIBOPT
This allows you to pass one or more command line arguments to the librarian.
Example: Set the page size to 32Kb
-LIBOPT-p32
Example: Embedded spaces enclosed in quotes.
"-LIBOPT -l -i"
-LIBPATH
This allows you to add one or more paths to be searched for library files.
This might be used when you don't want to permanently update the standard search paths.
Example:
-LIBPATH=c:\mylibs;d:\3rdparty;c:\lib\debuglibs
-LIBPATH=/usr/lib:/usr/local/lib:/usr/local/lib/mysql/
-PP 举例:
把b.d 文件移动 / 目录下,用bud a.d 编译就会提示找不到b.d,ok
bud a.d -PP/ # 提示找不到 /b.o,因为编译的b.o生成在了当前目录,而不是根目录
bud a.d -PP/ -op # 方案1:op是dmd的编译参数,表示在源文件的路径下生成.o文件
bud a.d -PP/ -odobj # 方案2:把.o文件都输出到 obj 目录下
dmd命令的-L参数:指定
-L 指定一个连接参数,比如:
-L-lpthread linux下链接libpthread.so
brf文件使用说明
brf文件就是定义了各种bud命令参数的集合。
文件扩展名是:.brf
举例:
文件名:final.brf
# 生成发行版本 # #符号是brf文件的注释符号
-T{Target}_release # 应用程序的名字
-release # Don't generate runtime checks.
-full # 重新编译所有文件
-cleanup # 编译完成后清除中间文件
-inline # 进行内联优化
运行方法:
bud a @final # 注意@符号
bud a @final --inline
# 把inline选项禁用;有警告,不知道原因;(
可以把源文件写到 brf 文件中
每行一个编译参数,没有顺序
可以用 -- 选项,把brf文件中的参数禁用了
不可以像Makefile文件一样,定义多个编译目标。定义多个brf文件吧
bud命令的默认brf文件叫 build.brf,如果要使用默认的brf,则可以不用指定文件名:
bud @
多放几个例子上来,备忘:
来自:http://dlang.group.iteye.com/group/topic/1072?page=6
-cleanup 编译后清理掉.o文件
-L-lpthread linux下链接libpthread.so
-LIBPATH=c:\db 设置库链接路径
libdb45.lib 直接链接windows下使用的lib文件
-op .o文件输出到源文件所在路径
-odobjs 把.o文件输出到objs文件夹
-T../bin/test 编译的可执行文件输出路径
# 一个简单的make.brf 文件
-cleanup
-op
-L-ldb
-LIBPATH=/home/lijie/dm/lib:/home/lijie/dmd/lib:/usr/local/BerkeleyDB.4.5/lib
src/test.d
-T../bin/test
其他bud参数
如果没有给出定义,就自己看文档吧,我也不大理解 ;)
-DCPATH 指定编译器的安装路径
-CFPATH 指定D配置文件的路径
-BCFPATH 指定Bud配置文件的路径
-RDF<file> 指定RDF文件(Rule Definition File)的路径
-MDF<file> 指定MDF文件(Macro Definition File)的路径
-nodef 不创建 MDF(Module Definition File)文件
-explicit 只编译指定的文件
-usefinal
-dll 如果源文件有DllMain()函数,默认会编译成Dll库;...
-gui 如果源文件有WinMain()函数,默认会编译成GUI程序;...
-help 显示帮助
-AutoWinLibs(=<Yes/No>)
-modules(=<name>)
-UMB=<Yes/No>
-R<option>
-emptyargs
-M<name>
-X<name>
Bud的编译安装
下载源程序
make -f Makefile.unix
./build build -full -op
ln -s build bud
后记:
因为我只是用D写写测试程序, 基本上就2、3个文件,最多有个C的链接库。
我的这点小需求,bud命令还是能很好处理的。更复杂的情况,我就不了解。
文中有些错误,和不肯定的地方,等我弄明白了再来修正吧。