发信人: dingdang()
整理人: zelor(2001-11-27 10:40:26), 站内信件
|
第一节, 上一节, 下一节, 最后一节, 回到目录
---------------------------------------------------------------------- ----------
编译程序和库
Automake的主要功能都是为了使编译C程序和库更加方便。
编译程序
若一个目录中的源码要被编译成可执行程序(相对库而言),则需用到 `PROGRAMS '主变量。程序可被安装到`bindir'、 `sbindir'、`libexecdir'、 `pkglibdir '或者哪里也不是(`noinst')。
比如:
bin_PROGRAMS = hello
在这个简单的例子中,所生成的`Makefile.in'将会包括生成名为 hello的可执行 程序的代码。hello_SOURCES变量用于指定哪些源文件需被编译:
hello_SOURCES = hello.c version.c getopt.c getopt1.c getopt.h system.h
这将使每个`.c'被编译为对应的`.o',然后进行连接以生成`hello'。
如果`prog_SOURCES'是必须的,但却未被定义,则其默认值为单个文件`prog.c' 。在上面的例子中,定义hello_SOURCES 实际上是可有可无的。
可以在同一个目录中编译多个可执行程序。多个程序可以共享一个源文件。源文 件必须在每个`_SOURCES'的定义中列出。
只有在`_SOURCES'中列出的头文件才会被包含在发布版本中,否则都将被忽略。 除非不是显而易见的,你不应在生成的`configure' 中包含变量`_SOURCES'中列 出的头文件,该文件将不会被分发。 Lex(`.l')和yacc (`.y')文件也可被列出, 参见对Yacc和Lex的支持。
Automake必须知道所有可能会被用到的源文件,即使不是在任何情况都会用到所 有这些文件。那些只会偶尔被用到的文件应在适当的`EXTRA_' 变量中列出。例如 ,如果`hello-linux.c'仅在某些情况下才会用于 hello程序,则`Makefile.am' 应包括:
EXTRA_hello_SOURCES = hello-linux.c
类似的,有时需要在配置时才决定需要编译哪些程序。例如,GNU的cpio 则只在 某些情况下才编译mt和rmt程序。
此时,你必须告诉automake所有你需要编译的程序,但同时使 `Makefile.in'利 用configure指定的程序。这可通过让configure替换每个`_PROGRAMS'的定义来实 现,同时在EXTRA_PROGRAMS中列出所有可选的目标程序。
如果需要连接在configure时未找到的库,可使用LDADD。这个变量实际上可用于 将任意的附加选项添加到连接程序的命令行中。
有时,在单个目录中编译的多个程序可能并不使用相同的连接需求。此时,你可 使用`prog_LDADD'变量(其中prog是出现在 `_PROGRAMS'变量中的程序名,一般使 用小写)来覆盖全局的 LDADD变量。(如果对某个程序定义了这个变量,则该程序 将不会使用LDADD。)
例如,在GNU cpio中, pax, cpio和mt 需要与`libcpio.a'连接。虽然rmt也位于 同一目录,但却不需要连接该库。同时,mt和rmt也仅在某些情况下才需编译。下 面是cpio的`src/Makefile.am'的内容:
bin_PROGRAMS = cpio pax @MT@
libexec_PROGRAMS = @RMT@
EXTRA_PROGRAMS = mt rmt
LDADD = ../lib/libcpio.a @INTLLIBS@
rmt_LDADD =
cpio_SOURCES = ...
pax_SOURCES = ...
mt_SOURCES = ...
rmt_SOURCES = ...
`prog_LDADD'并不适于传递与程序相关的连接选项 (除了`-l'和`-L'),而应使用 `prog_LDFLAGS'变量。
偶尔某个程序可能会依赖于一些并不在当前包中的其它目标,这可通过 `prog_D EPENDENCIES'变量来实现。每个程序都依赖于此变量的内容,但并不对其内容作 进一步的解释。
若没有指定`prog_DEPENDENCIES',则它的内容由Automake 自动设定,其值包括 `prog_LDADD'的内容(大部分配置已被替换),去掉`-l'和`-L'选项。剩下的配置 替换只有 `@LIBOBJS@'和`@ALLOCA@',它们之所以未被替换是因为在设定`prog_ DEPENDENCIES'时尚不知道它们的值。
编译库
编译库与编译程序基本相同,只是主变量的名字是`LIBRARIES'。库可以安装到l ibdir或pkglibdir。
关于如何使用Libtool和`LTLIBRARIES'主变量来编译共享库,请参考编译共享库 。
每个`_LIBRARIES'变量都是一个需编译的库的清单。例如,若要创建一个名为`l ibcpio.a'的库,但不需要安装,则可写为:
noinst_LIBRARIES = libcpio.a
`_SOURCES'变量指定所需的源文件。请注意库名是经过规范的 (canonicalized) (参见如何生成变量名),因此,与`liblob.a'相对应的`_SOURCES'变量名应该是 `liblob_a_SOURCES',而不是`liblob.a_SOURCES'。
可通过`library_LIBADD'指定需加入到库中的其它目标文件,可用于那些在conf igure时才能确定的目标文件。比如在cpio中:
libcpio_a_LIBADD = @LIBOBJS@ @ALLOCA@
对LIBOBJS和ALLOCA的特殊处理
Automake显式地识别对@LIBOBJS@和@ALLOCA@ 的使用,并且通过这些信息,加上 由`configure.in'得出的 LIBOBJS清单,可以自动确定在发布版本中需包含那些 源文件 (参见What Goes in a Distribution)。这些源文件在依赖关系跟踪方案 中同样被自动处理,参见 自动依赖关系跟踪。
在任何`_LDADD'或`_LIBADD'变量中的 @LIBOBJS@和@ALLOCA@都可被自动识别。
编译共享库
编译共享库要相对复杂一些。因此,可通过GNU Libtool (参见The Libtool Man ual)以一种平台无关的方式创建共享库。
Automake通过Libtool来创建在`LTLIBRARIES'主变量中指定的库。每个`_LTLIBR ARIES'变量都是一个需创建的共享库的清单。例如,要创建一个名为`libgettex t.a'的共享库,并安装到 `libdir', 则应写为:
lib_LTLIBRARIES = libgettext.la
请注意共享库必须指定安装路径,即不允许使用 `noinst_LTLIBRARIES'和`chec k_LTLIBRARIES'。
对每个库,变量`library_LIBADD'指定需加入到共享库中的额外的 libtool目标 文件。变量`library_LDFLAGS'则包含附加的 libtool选项,比如`-version-inf o'或`-static'。
在一个普通的库需使用@LIBOBJS@的地方,使用libtool的库则必须使用@LTLIBOB JS@。这时因为libtool所操作的目标文件并不需要以 `.o'结尾。详细信息可参考 libtool的手册。
对于安装到某些目录下的库文件,automake会自动提供适当的 `-rpath'选项。但 是,对于在configure时才可确定的库(以及那些EXTRA_LTLIBRARIES指定的库), automake 并不知道最终的安装目录。对于这些库,你必须手工在`_LDFLAGS' 中 加上适当的`-rpath'选项。
用于编译程序的变量
偶尔需要知道Automake使用哪一个`Makefile'变量用于编译,比如有时你需要手 工进行编译。
一些变量继承自Autoconf,包括:CC, CFLAGS, CPPFLAGS, DEFS, LDFLAGS和LIB S。
下面是一些Automake自己定义的变量:
INCLUDES
一系列`-I'选项。如果你需检索一些特殊目录,则可在 `Makefile.am'中设置此 变量。automake已经自动提供了一些`-I'选项。特别是它会生成一个 `-I$(srcd ir)'和一个`-I'指向包含 `config.h'文件的目录(如果已经定义了AC_CONFIG_HE ADER 或AM_CONFIG_HEADER的话)。 INCLUDES实际上还可指定除`-I'以外的cpp 选 项。比如,有时它可用于传递任意的`-D'选项到编译器。
COMPILE
指定用于编译C源程序的真正命令。文件名将被添加到整个命令行的末尾。
LINK
指定用于连接C源程序的真正命令。
对Yacc和Lex的支持
Automake对YACC和LEX有一些特别的(idiosyncratic)支持。
Automake假定由yacc/lex生成的`.c'文件与输入文件有相同的文件基本名。例如 ,对于yacc源文件`foo.y', automake会认为输出的中间文件名为`foo.c'(而不是 传统的文件名`y.tab.c')。
Automake利用yacc源文件的扩展名来决定结果文件是`C' 还是`C++'文件。若扩展 名为`.y'则输出为 `.c',若为`.yy'则输出为`.cc', `.y++'输出为`c++',`.y xx'输出为 `.cxx'。同样,对于lex的源文件,`.l', `.ll', `.l++'和`.lxx'等 扩展名都可被识别。
你不应在任何`SOURCES'变量中显式地指定所需的中间文件名(`C'或`C++'),只列 出源文件即可。
由yacc(或lex)生成的中间文件也会被包含在发布版本中,这样用户就不一定需要 拥有yacc或lex。
如果指定了yacc源文件,则必须在`configure.in'中定义 `YACC'变量。最简单的 方法就是使用`AC_PROG_YACC'宏。
类似的,若使用了lex源文件,则需在`configure.in'中定义 `LEX'变量,可通过 `AC_PROG_LEX'宏。此外,Automake还要求你使用`AC_DECL_YYTEXT'宏,因为它需 要知道`LEX_OUTPUT_ROOT'的值。
Automake允许在单个程序中包含多个yacc(或lex)源文件。Automake通过一个叫y lwrap的小程序在子目录中运行yacc(或 lex)。这是因为yacc的输出文件名是固定 的,而并行执行的 make可能会同时执行yacc的多个实例。 ylwrap与automake一 起分发。它应位于`AC_CONFIG_AUX_DIR' 指定的目录或者当前目录(如果在`conf igure.in'中没有使用该宏)。
对于yacc, 简单的锁管理机制是不足够的。 yacc的输出总是使用相同内部符号表 ,因此不可能将两个 yacc语法语法分析器连接到同一个可执行程序中。
建议在gdb中使用下面的名字替换:
#define yymaxdepth c_maxdepth
#define yyparse c_parse
#define yylex c_lex
#define yyerror c_error
#define yylval c_lval
#define yychar c_char
#define yydebug c_debug
#define yypact c_pact
#define yyr1 c_r1
#define yyr2 c_r2
#define yydef c_def
#define yychk c_chk
#define yypgo c_pgo
#define yyact c_act
#define yyexca c_exca
#define yyerrflag c_errflag
#define yynerrs c_nerrs
#define yyps c_ps
#define yypv c_pv
#define yys c_s
#define yy_yys c_yys
#define yystate c_state
#define yytmp c_tmp
#define yyv c_v
#define yy_yyv c_yyv
#define yyval c_val
#define yylloc c_lloc
#define yyreds c_reds
#define yytoks c_toks
#define yylhs c_yylhs
#define yylen c_yylen
#define yydefred c_yydefred
#define yydgoto c_yydgoto
#define yysindex c_yysindex
#define yyrindex c_yyrindex
#define yygindex c_yygindex
#define yytable c_yytable
#define yycheck c_yycheck
上面这些定义可用于bison、byacc和传统的 yacc。如果你发现某个语法分析器使 用了上表中没有的符号,可直接将它加入表中。
C++以及其它语言
Automake对C++完全支持,如果需要,以后还可加入对其它语言的支持。
包含有C++代码的软件包必须在`configure.in'中定义输出变量 `CXX',最简单的 方法是使用AC_PROG_CXX宏。
此外,还需定义一些额外的变量:
CXX
C++编译器的名字。
CXXFLAGS
传递给C++编译器的选项。
CXXCOMPILE
指定用于编译C++源程序的真正命令。文件名将被添加到整个命令行的末尾。
CXXLINK
指定用于连接C++源程序的真正命令。
自动de-ANSI-fication
虽然GNU的标准允许使用ANSI C, 但这会影响到程序在一些老的编译器上的可移植 性(特别是SunOS)。
Automake可使你避开这个问题,即在实际编译之前自动对每个源文件进行 "de-A NSI-fying"。
如果`Makefile.am'变量AUTOMAKE_OPTIONS (参见 改变Automake的行为)包含ans i2knr选项 ,则会在生成的`Makefile.in' 中插入处理de-ANSI-fication的代码 。
这将使目录中的每个C源文件都被当作ANSI C程序。如果所用的是 ANSI C编译器 ,则直接使用这些文件。否则,将执行ansi2knr 将源文件转换为K&R C, 然后才 进行编译。
ansi2knr程序并不太聪明,它假定源文件已按一种特定的方式格式化,可参考an si2knr的手册。
对De-ANSI-fication的支持需要在与源文件相同的目录中存在`ansi2knr.c' 和` ansi2knr.1'文件。这些文件随Automake一起分发。同时,在 `configure.in'中 必须调用AM_C_PROTOTYPES宏。
Automake会在当前软件包的其它一些目录中自动查找ansi2knr 的支持文件,这可 通过在ansi2knr选项中加上适当的相对路径来完成。例如,假定软件包的`src'和 `lib'目录中包含ANSI C代码,而`ansi2knr.c'和`ansi2knr.1'文件位于`lib'目 录,则`src/Makefile.am'应写为:
AUTOMAKE_OPTIONS = ../lib/ansi2knr
若没有给出目录前缀,则假定文件位于当前目录。
自动依赖关系跟踪
作为一个开发人员,因为包含文件的依赖关系改变而不断地更新 `Makefile.in' 文件是一件很烦人的事情。automake 提供了一种方法可自动地跟踪依赖关系的改 变,并在生成的 `Makefile.in'中反映依赖关系的变化。
目前这个功能需要使用GNU的make和gcc。将来有可能会提供一个不同的依赖性管 理程序。在此期间,如果当前目录下定义了任何C程序或库,则会自动打开此模式 ,因此,如果你使用非GNU 的make,则可能会得到一个`Must be a separator'的 错误。
当你决定生成一个发布版本时,dist目标 将会以`--include-deps'和其它选项重 新运行 automake。这将使以前已经生成的依赖性被插入到新生成的 `Makefile. in'中,并进入发布版本。这一步骤也会关闭插入依赖性生成代码,所以下载的发 布版本的用户即使没有使用GNU的 make和gcc也不会出现错误。
当将依赖关系加入`Makefile.in'时,所有与系统相关的依赖关系被自动移除。可 在`OMIT_DEPENDENCIES'中列出这些文件。 比如,所有对系统头文件的引用都将 被automake去除。又如,假如在`configure.in'中使用了`AM_WITH_REGEX',则任 何对`rx.h'或`regex.h'的依赖都被去除,因为直到用户配置这个软件包时才能知 道应该使用哪一个。
实际上automake可以足够聪明地处理与正规表达式头文件相关的问题。如果使用 了`AM_GNU_GETTEXT',它还会自动忽略`libintl.h'。
可通过在AUTOMAKE_OPTIONS中指定 no-dependencies来禁止自动依赖关系跟踪。
当你解开一个由make dist生成的发布版本,此时你又想重新打开自动依赖关系跟 踪功能,重新运行automake即可。
实际的依赖关系文件放在build目录的名为`.deps'的子目录中。可以安全地删除 这些文件,在下次编译时会自动生成这些文件。
---------------------------------------------------------------------- ----------
第一节, 上一节, 下一节, 最后一节, 回到目录
-- ※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.104.84.141]
|
|