Tmake使用指南
译者:一风(兰州大学高性能计算机试验室 cnyifeng@263.net) tmake是一个很好用的生成和管理makefile的工具,他是由Trolltech这家公司开发的,用perl写成。Trolltech这家公司的主打产品大家都知道是Qt。
如果不是用tmake来管理makefile的话,那将会是一件痛苦的事情,虽然有autoconf等工具,但毕竟还是十分繁杂的,现在tmake将我们完全从繁琐的生成makefile的过程中解脱出来,只要很简单的步骤就可以生成makefile了。其实tmake原本写了使用在Qt上的,只不过不用Qt,我们也可以享受到他的好处,perl在这里面充分体现了他的强大,我一直以为,perl是一个很好的用于系统管理的语言。如果你会perl的话,你可以自己试着修改tmake。 由于tmake是基于perl的,所以请你确认你的机子上安装了perl。tmake在windows和unix上都有支持。而且它是免费的。本文以linux为平台讲述。 好了,下面我开始介绍tmake的安装1。确认你有perl5以后的版本并安装了(windows用户可选)2。在linux上解压tmake tar.gz,在windows上解压.zip文件。3。设置好tmake路径参数(参见下文)4。加入tmake/bin去你的执行路径。
下面是一些例子:Unix Bourne shell:
TMAKEPATH=/local/tmake/lib/linux-g++ PATH=$PATH:/local/tmake/bin export TMAKEPATH PATH
Unix C shell: setenv TMAKEPATH /local/tmake/lib/linux-g++ setenv PATH $PATH:/local/tmake/bin
Microsoft Windows: set TMAKEPATH=c:/tmake/lib/win32-msvc set PATH=%PATH%;c:/tmake/bin在上面设置的路径里面有各种平台支持文件和tmake执行文件。tmake支持的平台有: AIX, Data General, FreeBSD, HPUX, SGI Irix, Linux, NetBSD, OpenBSD, OSF1/DEC, SCO, Solaris, SunOS, Ultrix, Unixware and Win32
UNIX用户请注意:tmake默认的是perl安装在/usr/bin下面,如果你的不是的话,请修改tmake文件第一行的参数。
下面我们开始学习tmake的使用:我假设你有一个小的qt程序,他由一个C++ header和两个source file组成。首先,你要创建一个tmake工程文件,如:hello.proHEADERS = hello.hSOURCES = hello.cpp main.cppTARGET = hello下面我们来产生makefiletmake hello.pro -o Makefile最后我们执行make命令编译hello这个程序。
Makefile模板Tmake发行版本中有以下三个模板App.t 用来创建生成发布使用程序的makefileLib.t 用来创建生成libraries的makefileSubdirs.t 用来创建目标文档在目录中的makefileTmake.conf 这个configuration文件包含了编译选项和各种资源库我们上面创建的hello.pro工程文件并没有包含进模板或者配置选项。默认的模板是app.t,默认的配置是“qt warn_on release“。 下面这个配置文件和上面的功能上是一样的TEMPLATE = appCONFIG = qt warn_on releaseHEADERS = hello.hSOURCES = hello.cpp main.cppTARGET = helloMakefile配置选项配置选项可以用在app.t和lib.t中,他们用来指示使用什么编译选项和连接什么库文件。他们有以下几个:1.控制编译选项的release 用来生成最优化编译(用于发布的软件),如果选了”debug”,此选项忽略debug 调试时使用该选项,打开debug功能warn_on 打开警告选项,产生比正常情况下多的警告。如果选了”warn_off”,此选项忽略warn_off 关闭警告选项2.控制程序/库文件类型的qt 如果是生成qt程序,打开他(改选项是默认支持的)opengl 不说也知道是编OPENGL时用的thread 用来支持线程X11 用来支持X11windows 支持WINDOWSconsole 同样是WINDOWS下的控制台程序dll 生成动态连接库时使用staticlib 生成静态连接库时使用举个例子:假如我们的hello程序需要qt和opengl支持,并且还要打开debug,那么我们的配置就该是这样的TEMPLATE = appCONFIG = qt opengl debug(注意本行的改变)HEADERS = hello.hSOURCES = hello.cpp main.cppTARGET = hello应用程序模板(app.t)此模板支持以下选项HEADERS 头文件SOURCES 原程序文件TARGET 目标文件DESTDIR 放置目标文件的目录DEFINES 告知C预处理编译器打开“-D“选项INCLUDEPATH 设置库文件路径(-I选项)DEPENDPATH 设置相关搜索路径DEF_FILE WINDOWS专用:连接一个.def文件RC_FILE WINDOWS专用:使用.rc文件(编译为.res)RES_FILE WINDOWS专用:连接.res文件库模板(lib.t)该模板让你编译创建一个动态或静态库。Lib.t支持和app.t相同的选项,同时还支持一个app.t不支持的选项:VERSION。VERSION 是一个版本号。例如:1.40,版本号对于动态库是十分重要的。Subdirs模板(subdirs.t)当你的程序文件太多时,你可以使用它。他将你所列出的文件夹全部包括进去,并进行编译。
工程文件的语法工程文件十分好写,你可以随意添加或删减各个选项。设置一个选项如下:HEADERS = gui.h xml.h url.h如果你的选项不能再一行内写完的话,你可以使用’/’来分割他例如:HEADERS = gui.h / xml.h / url.h工程文件使用空白来分割各个元素,这也就表明你不能将带有空格的元素用在工程文件中(除了INCLUDEPATH选项,他使用“;”来分割元素)。例如:INCLUDEPATH = C:/Program Files/DBLib/Include;C:/qt/includeTmake支持变量扩展,使用”$$”来扩展工程变量ALLFILES = $$HEADERS $$SOURCES你可以赋值给工程变量,也可以添加变量例如:A = abcX = xyzA += def # A = abc defX *= xyz # X = xyzB = $$A # B = abc defB -= abc # B = defX /= s/y/Y/ # X = xYz*=操作符添加值给变量(如果变量没有该值的话)。/= 执行规则表达式。当然了,你还可以在命令行下赋值(运行tmake时)。例如,如果你想要打开debug选项的话,可以这样tmake "CONFIG+=debug" hello.pro当你想对不同平台进行编译时使用unix:或者win32:标志符SOURCES = common.cpp # common for all platformsunix:SOURCES += unix.cpp # additional sources for Unixwin32:SOURCES += win32.cpp # additional sources for Windowsunix:LIBS += -lm # on Unix we need the math lib而且,你可以设置平台编译器相关选项,方法如下linux-g++:TMAKE_CFLAGS = -fno-rtti同时你还可以自定义模板,不过那要你对tmake比较了解才行。运行tmake写了那么多的如何创建工程文件的东东,下面到了如何运行tmake的时候了。Tmake的使用方法如下:tmake [选项] project files or project settings选项:-e expr 执行perl表达式,忽略模板文件-nodepend 不产生关联信息-o file 指定输出文件(常用)-t file 制定模板文件(覆盖工程文件中的模板变量)-unix 强制使用unix模式-v 打开debug和warn_on选项-win32 强制使用win32模式默认的工程文件后缀名为”.pro”,默认的模板文件后缀为”.t”.如果你不指定他们的话,tmake会自动为你加上这是一个基本的使用方式:(工程文件是hello)tmake hello –o Makefile下面是打开debug的使用方式:tmake hello “CONFIG+=debug” –o Makefile这是指定TMAKEPATH地用法:tmake "TMAKEPATH=/local/tmake/lib/hpux-g++" hello.pro -o Makefile这是执行PERL表达式的用法(打印头文件和源文件名)tmake hello –e ‘Expand(“HEADERS”,”SOURCES”)’请注意:所有的命令行变量设置请放到工程文件后面,否则工程文件将会覆盖他们。其他小工具progenprogen为你创建工程文件,使用方法如下:progen –n hello –o hello.pro如果没有指定.cpp或.h文件的话,progen或搜索所有在当前目录和他的子目录的所有文件(除了moc_*.cpp)用法:progen [可选项] [C/C++ 头文件和源文件]可选项:-lower 将文件名小写(在windows下比较有用)-n name 定义工程名(即目标名)-o file 定义输出文件-t file 制定模板文件
高级话题如果你还想要制定特殊的选项或者想添加makefile规则的话,那么就请继续往下看罢如果你想要平台关联的设置的话,你可以在工程文件中这样写solaris-cc:TMAKE_CC = /opt/bin/CC_5.0solaris-cc:TMAKE_CFLAGS = -ptsunix:TMAKE_LIBS = -lXextwin32:INCLUDEPATH = c:/myincludewin32-borland:DEFINES = NO_BOOL创建自己的模板如果你懂perl的话,那么对你来说tmake就没有什么限制了。不过首先你要了解一下tmake是如何工作的。模板处理当你运行tmake时,他首先读取tmake.conf文件,这个配置文件和工程文件的语法是一样的。然后tmake读取工程文件并且设置从工程文件中读取的变量。例如:HEADERS,SOURCES等等。所有的变量都存储在一个名叫project的全局散列数组中。例如,在处理完tmake.pro后$project{“SOURCES”}包含了”hello.cpp main.cpp”。当tmake.conf和工程文件都读完了后,tmake开始一行一行的读取模板文件并执行任何他发现的perl脚本? 在”#$”后该行的所有字符都被认为时perl脚本? 从”#${”到”#$}”的所有字符也被认为是perl脚本? “#!”后的该行全部是注释? 其他的直接被输出例子:#! This is a comment which will be removed.This text will appear in the output.#$ $text = "The header file(s) are: " . $project{"HEADERS"};# This text also appears in the output.#${ $a = 12; $b = 13; $text = $a * $b;#$}That's all.输出语句: This text will appear in the output. The header file(s) are: hello.h # This text also appears in the output. 156That's all.将tmake与Lex和yacc联合使用标准的tmake模板知道如何处理C和C++文件,但也许你还要处理其他的文件并要将它们连接进入你的工程中。一个典型的例子是当你建造一个分析器时你要处理lex和yacc文件。分析模板: #! #! parser.t: This is a custom template for building a parser #! #$ IncludeTemplate("app.t");
####### Lex/yacc programs and options
LEX = flex YACC = #$ $text = ($is_unix ? "yacc -d" : "byacc -d");
####### Lex/yacc files
LEXIN = #$ Expand("LEXINPUT"); LEXOUT = lex.yy.c YACCIN = #$ Expand("YACCINPUT"); YACCOUT = y.tab.c YACCHDR = y.tab.h PARSER = #$ Expand("PARSER");
####### Process lex/yacc files
$(LEXOUT): $(LEXIN) $(LEX) $(LEXIN)
$(PARSER): $(YACCIN) $(LEXOUT) $(YACC) $(YACCIN) #$ $text = ($is_unix ? "-rm -f " : "-del ") . '$(PARSER)'; #$ $text = ($is_unix ? "-mv " : "-ren ") . '$(YACCOUT) $(PARSER)'; 分析模板加入一些用于建造lex和yacc部分的规则。这个模板可用于unix或windows中,应为他依据$is_unix变量产生不同规则。想要学习更多的请参考reference manual(未翻译)Example project file: TEMPLATE = parser.t CONFIG = console release LEXINPUT = lexer.l YACCINPUT = grammar.y PARSER = parser.cpp SOURCES = $$PARSER / node.cpp / asmgen.cpp TARGET = parser
这里我们使用宏变量以避免写parser.cpp两次。计算代码行数由于tmake是基于perl的,所以它允许你创建自己的用于其他用途的模板(即不用于产生makefile的模板)模板wc.t(一个用于计算代码行数的模板) #! Template that count number of C++ lines. The number of C++ code lines for #$ $text=$project_name; #${ $files = $project{"HEADERS"} . " " . $project{"SOURCES"}; $text = `wc -l $files`; #$}这样运行:tmake –t wc hello输出为: The number of C++ code lines for hello.pro 25 hello.h 98 hello.cpp 38 main.cpp 161 total只有当你安装了wc.t后你才可以这样做。
译后感:这是我第一次这样用心的去翻译一篇文章,因为我认为这篇文章实在是太好了,对于我们这些linux/unix fans们来说是一个福音,我也是望着篇文章能带给你帮助。如果这样的话,那我的努力就没有白费。本文你可以自由转载,但请不要去掉版权信息,也不要用于商业用途译者:一风(兰州大学高性能计算机试验室cnyifeng@vip.163.com)如果你有什么提议或发现错误的话,请告诉我,如果你认为本文对你有用的话,也请你告诉我,让我知道我还做了点有用的东西。
