标签 Makefile 下的文章

使用Make的命令行变量

有了BuildBot搭建的持续集成环境还远未结束,具体的构建脚本还得自己来写。我们用的是Make工具,对应要编写的脚本就是Makefile。

Make是日常代码构建常用的工具,尤其是绝大多数C和C++项目都会将Make作为首选构建工具。平时多数情况大家都是直接敲入make命令便开始了构建过程,很少有人为make传入什么参数的(调试Makefile的情况除外)。但是有些时候自定义的Make命令行变量还是很有用处的,特别是在将Make与持续集成环境集成的时候。

实际上这个话题是源于我在搭建持续集成环境时遇到的一个实际问题。我们的产品的目标之一就是支持在不同平台上运行。这样我们需要在不同平台下都能进行构建,这也要求我们的Makefile可以自适应多种环境。以前的产品没有多平台运行的需求,其Makefile的实现也就没有考虑到这一点。在做平台移植的过程中,我们对Makefile脚本做了调整,不过虽然其可以满足在多平台上Build的要求,但是在某些情况下Build前需手工修改Makefile中的某些开关变量,比如是进行64bit编译还是32bit编译等。

这样的Makefile是不能用于持续集成环境下的多平台构建的,因为是自动构建,我们无法在中间进行人工干预。这时我们就需要借助Make命令行变量的帮助来解决这一问题了。举一个简单的例子,看下面的C源文件和对应的Makefile:

/* foo.c */
int main() {
    printf("sizeof(long) = %d\n", sizeof(long));
}

#
# Makefile
#

CMODE = 64-bit

ifeq ($(CMODE), 64-bit)
    CFLAGS += -m64
endif
   
all:
    gcc $(CFLAGS) -o foo foo.c   

显然Makefile中CMODE的取值不同,编译出的foo执行的结果就不同。但我们确有这样的需求,我们需要通过控制CMODE的值来决定Build结果。我们不想改动Makefile,我们可以通过Make的命令行变量设置来解决这个问题。我们只需在执行make时传入"CMODE=32-bit"这个参数即可让Build过程按照非64位方式进行。

一般的带命令行变量的make命令格式是:make [variable1=value1 variable2=value2 ... ... ]。make命令行中传入的变量会覆盖Makefile文件中定义的同名的并且没有使用override修饰的变量。命令行上的变量的赋值也可以用支持直接展开的:=赋值符号。

有了这种方法,我们就可以在BuildBot的build factory实例化时传入带参数的step了,即可以通过不同参数来控制在各个平台上的自动构建了。

使用Libtool创建库文件

除了autoconf和automake,GNU的autotools工具包中还有一种工具,它就是libtool。顾名思义,libtool是一个关于库文件制作、安装和使用的工具,它屏蔽了各个平台在库制作、安装和使用方面的差异,为上层提供了统一的接口。你可以直接使用libtool创建静态或共享库,也可以将libtool与autoconf、automake结合在一起使用。第二种方式显然更具实际意义,也更为简单。

在一个使用autoconfautomake构建的编译环境中添加libtool的支持,只需改动几处即可:
首先,你需要在configure.in(或configure.ac)中添加AC_PROG_LIBTOOL宏(注意:去掉AC_PROC_RANLIB宏)。
其次,修改Makefile.am:
如果是建立库文件,则需将lib_LIBRARIES改为lib_LTLIBRARIES,同时将库的后缀名由.a改为.la,这将告诉automake采用libtool来创建相关库:
lib_LIBRARIES = libfoo.a => lib_LTLIBRARIES = libfoo.la
libfoo_a_SOURCES = libfoo.c => libfoo_la_sources = libfoo.c

如果是使用上面生成的库文件,则将可执行程序链接的库改为.la,如:
fooapp_SOURCES = fooapp.c
fooapp_LDADD = libfoo.la

更新完上述配置后,删除aclocal.m4,执行aclocal和autoreconf,此时如果你的系统中没有安装libtool的话,autoconf会提示"undefined macro AC_PROG_LIBTOOL",安装libtool(sudo apt-get install libtool)后,错误提示消失。autoreconf会初始化libtool环境,并将libtool和ltmain.sh两个脚本拷贝到你的工程目录下。由于修改了Makefile.am,你还需要重新执行依次automake。

后面的操作大家就很熟悉了,configure -> make -> make install。libtool默认状态下会将静态库(.a)和共享库(.so)都生成出来,不过你可以通过configure命令行参数来控制这一切:
–disable-shared 不生成共享库
–disable-static 不生成静态库
–enable-shared 生成共享库
–enable-static 生成静态库

你同样可以在configure.in中控制创建的库的类型,比如,在configure.in中增加AC_DISABLE_SHARED宏就可以让libtool只创建静态库,而不生成共享库。

执行make install将库安装完后,你会发现在安装的lib目录下还保留有一份.la文件,通过该.la文件,我们可以继续通过libtool来使用这些库。当然你也可以完全略过.la而直接链接静态库(.a)和共享库(.so)。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats