在开始之前
这里我们用 Vala 语言和 GTK+ 来展示如何使用 Automake。
首先创建 src/sp-gui.vala:
1 2 3 4 5 6 7 8 9 10 11 12 | using Gtk; int main( string [] args) { Gtk.init( ref args); var win = new Gtk.Window(WindowType.TOPLEVEL); win.destroy.connect(Gtk.main_quit); win.title = "Salamat Pagi" ; win.show_all(); Gtk.main(); return 0; } |
这段代码会生成一个标题为 Salamat Pagi 的空白窗口。这段代码可以使用以下命令测试:
1 2 | > valac sp-gui.vala --pkg gtk+-3.0 > . /sp-gui |
开始折腾 Automake
首先创建 Makefile.am 文件:
1 | SUBDIRS = src |
然后创建 src/Makefile.am 文件:
1 2 3 4 5 6 | bin_PROGRAMS = sp-gui sp_gui_SOURCES = sp-gui.vala # 很遗憾我还没找到有什么好办法把这个 VALAFLAGS 消除掉 sp_gui_VALAFLAGS = --pkg gtk+-3.0 sp_gui_CFLAGS = $(GTK_CFLAGS) sp_gui_LDADD = $(GTK_LIBS) |
我们已经知道,Automake 是把 Makefile.am 转换成 Makefile.in 的东西,理论上来说 automake 是增强 autoconf 功能的程序,所以我们不得不把 autoconf 和 automake 放在一起来讲。不信的话,你现在试试,automake 会报错 configure.ac 缺少一些命令。
现在我们把 configure.ac 改成下面的样子:
1 2 3 4 5 6 7 8 9 | AC_INIT([SalamatPagi], [0.1], [bug-report@address]) AM_INIT_AUTOMAKE AM_PROG_VALAC AC_PROG_CC PKG_CHECK_MODULES([GTK], [gtk+-3.0]) AC_SUBST([GTK_CFLAGS]) AC_SUBST([GTK_LIBS]) AC_CONFIG_FILES([Makefile src/Makefile]) AC_OUTPUT |
然后依次执行 aclocal, autoconf, automake -a --foreign。值得注意的是,这里必须要有 AC_PROG_CC,因为 Vala 实际上是将代码编译成 C 代码的,所以 C 语言需要的配置这里也要有(这正是我选择 Vala 为示例的原因,不用 Vala 的话,完全可以自己修改为 C语言版本),如果你以后要用 Vala 编程,应该注意。
automake 的参数
--add-missing (-a) 可以为你自动安装一些必须的脚本。
--foreign 则不强求你安装一些无聊的文档文件,比如 README,INSTALL,NEWS 之类的。如果你不想每次都这么做,可以把代码改成 AM_INIT_AUTOMAKE([foreign])
现在你可以试试 make 和 make clean 了。
同时生成多个可执行文件
我们这里提供一个小型 CLI 版本 Salamat Pagi 程序,创建文件 src/sp-cli.c:
1 2 3 4 5 6 | #include <stdio.h> int main( int argc, char *argv[]) { printf ( "Salamat Pagi!\n" ); return 0; } |
按着上面的办法,我们在 src/Makefile.am 中添加:
1 2 | bin_PROGRAMS += sp-cli sp_cli_SOURCES = sp-cli.c |
响应 configure 参数
这里把 CLI 作为可选项。configure.ac 中添加:
1 2 3 4 5 6 7 8 | AC_ARG_WITH([cli], [ --with-cli Command line interface], [case "${withval}" in yes) cli=true ;; no) cli=false ;; *) AC_MSG_ERROR([bad value ${withval} for --with-cli]) ;; esac],[cli=false]) AM_CONDITIONAL([WITH_CLI], [test x$cli = xtrue]) |
--with-xx 的 value 是 withval,那么 --enable-xx 的 value 就是 enableval。
Makefile.am 中原有 sp-cli 的内容改为:
1 2 3 4 | if WITH_CLI bin_PROGRAMS += sp-cli sp_cli_SOURCES = sp-cli.c endif |
现在,要编译 CLI 版本,就不得不 configure --with-cli=yes 了。
如果你想让 GUI 版本成为可选,想想应该修改哪些文件?没错,正是 configure.ac 和 src/Makefile.am。首先 configure.ac 中应该按照需求进行 PKG_CHECK_MODULES,然后再在 src/Makefile.am 中按需要编译 GUI 版本程序,甚至你可以让 AM_PROG_VALAC 按需求调用!
编译命令很长很烦?
automake 有 silent rules,可以把很长的命令缩短到 CC xx.c!有两个办法,一个是在 configure 的时候提供 --enable-silent-rules,另一个是在 configure.ac 里面提供 AM_SILENT_RULES([yes])。
一些测试程序?
有些程序是我们用来测试的,并不打算被 make install 安装到系统中,那么我们这时会使用 noinst_PROGRAMS 而不是 bin_PROGRAMS。以 noinst 前缀为 target 的文件,全部不会被安装。
安装其他文件
现在我们已经基本完成了大致的程序构造,make install 和 make uninstall 已经可以实作了!那么假如我们想要安装一些别的文件怎么办呢?比如说 Glade 生成的 UI 描述文件,我们一般希望这些东西安装到 ${prefix}/share/ProgramName 目录里面。我们创建 common/somethingRequired.txt:
1 | This text file is required by Salamat Pagi! |
为了让 automake 能管理到 common 目录,我们需要修改 Makefile.am:
1 | SUBDIRS = common src |
同时创建 common/Makefile.am:
1 2 | commondir = $(datadir)/$(PACKAGE) dist_common_DATA = somethingRequired.txt |
另外别忘了修改 configure.ac。
这些文件一般在项目的 data 文件夹里面,不过因为之前已经创建好了 common,这里用就是了。
此外需要注意的是,一定不要在 Makefile.am 中使用绝对路径!
这里 datadir 会展开为 $(prefix)/share。现在我们就能试试了。安装后在 /usr/local/share/salamatpagi 下看看?另外值得注意的是,make uninstall 不会删掉目录!所以最终还是建议打包成 rpm 或者 deb。
回顾操作流程与自定义目标
我们现在已经知道 automake 可以将 Makefile.am 转换成 Makefile.in 交给 configure 具体化。那么自定义 target 又如何呢?很简单,直接在 Makefile.am 里面写就行了。
我们在 Makefile.am 里面添加:
1 2 | greet: @echo yo! |
现在 make greet 就能显示出来一个 yo! 了!想想看为什么这样可以?