需求是这样的:
要写一个公用的C库libtoken,该库会被多个C/C++模块使用,但是由于这些模块是在不同的环境下build的,比如CentOS 5.3、CentOS 6.3、64bit、32bit……,因此不方便做成一个.so或.a文件放那儿,让这些模块直接取做link,因为那是会出问题滴!所以,让每个模块在build之前,先在和自己模块相同的环境下build libtoken库,把build出来的库文件以及库的头文件放到自己的源文件路径下,再去build自己的模块。
同时libtoken要通过log4c库写log,这就导致log4c库也不能直接放一个.a或.so到libtoken库的路径下。
解决办法:
将log4c的源代码放到libtoken库的路径下,修改libtoken库的Makefile,使得build libtoken库之前会先build 和install log4c库,将build出来的liblog4c.a和log4c的头文件通过make install的方式,拷贝到libtoken路径下,最后再build libtoken库。
简单示例:
假设我们写一个使用log4c的log4c-tetst工程,目录结构如下。log4c-1.2.4是下载的log4c源码,vendors/log4c是要放置log4c库文件和头文件的地方。
log4c-test >main.cpp >Makefile >log4c-1.2.4 >vendors >>log4c
LOG4C_DIR = ./log4c-1.2.4 LOG4C_VENDOR_DIR = ./vendors/log4c LOG4C_VENDOR_INCLUDE_DIR = $(LOG4C_VENDOR_DIR)/include LOG4C_VENDOR_LIB_DIR = $(LOG4C_VENDOR_DIR)/lib TARGET = ./test all: build-log4c g++ main.cpp -o $(TARGET) -I$(LOG4C_VENDOR_INCLUDE_DIR) $(LOG4C_VENDOR_LIB_DIR)/liblog4c.a -lexpat build-log4c: cd $(LOG4C_DIR) && ./configure --prefix=`pwd`/../vendors/log4c && make && make install clean: rm $(TARGET) -f cd $(LOG4C_DIR) && make uninstall
执行make之后的目录结构:
log4c-test >main.cpp >Makefile >log4c-1.2.4 >vendors >>log4c >>>bin >>>etc >>>include >>>lib >>>share
注意:
1)log4c源码build出来的文件都在log4c源码的 src/log4c/.libs 隐藏文件夹下。这里我要的只是其中的liblog4c.a。
2)Makefile中g++ main.cpp一行中,最后有个貌似多余的"-lexpat",如果没有它,make时会出现下面的错误。原因(参考)是,默认情况下,log4c库依赖于expat做log4crc xml文件解析,并且log4c库要放在其他链接的库的前面。(可以加上--without-expat选项,不使用expat库而使用log4c自定义的解析器)
g++ main.cpp -o ./test -I./vendors/log4c/include ./vendors/log4c/lib/liblog4c.a ./vendors/log4c/lib/liblog4c.a(domnode-expat.o): In function `sd_domnode_read': /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:316: undefined reference to `XML_ParserCreate' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:321: undefined reference to `XML_SetStartElementHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:322: undefined reference to `XML_SetEndElementHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:323: undefined reference to `XML_SetCharacterDataHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:324: undefined reference to `XML_SetCommentHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:325: undefined reference to `XML_SetUserData' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:327: undefined reference to `XML_Parse' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:355: undefined reference to `XML_ParserFree' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:328: undefined reference to `XML_GetCurrentByteIndex' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:328: undefined reference to `XML_GetCurrentColumnNumber' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:328: undefined reference to `XML_GetCurrentLineNumber' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:328: undefined reference to `XML_GetErrorCode' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:328: undefined reference to `XML_ErrorString' ./vendors/log4c/lib/liblog4c.a(domnode-expat.o): In function `sd_domnode_fread': /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:242: undefined reference to `XML_ParserCreate' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:247: undefined reference to `XML_SetStartElementHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:248: undefined reference to `XML_SetEndElementHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:249: undefined reference to `XML_SetCharacterDataHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:250: undefined reference to `XML_SetCommentHandler' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:251: undefined reference to `XML_SetUserData' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:258: undefined reference to `XML_GetBuffer' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:268: undefined reference to `XML_ParseBuffer' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:301: undefined reference to `XML_ParserFree' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:269: undefined reference to `XML_GetCurrentByteIndex' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:269: undefined reference to `XML_GetCurrentColumnNumber' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:269: undefined reference to `XML_GetCurrentLineNumber' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:269: undefined reference to `XML_GetErrorCode' /home/yasi/log4c-test/log4c-1.2.4/src/sd/domnode-expat.c:269: undefined reference to `XML_ErrorString' collect2: ld returned 1 exit status make: *** [all] Error 1
3)Makefile中,cd $(LOG4C_DIR)一行中,如果用 LOG4C_VENDOR_DIR 代替 `pwd`/../vendors/log4c,则会得到错误提示“不要使用相对路径”。如果把这一行和LOG4C_VENDOR_DIR定义换成下面两句,则虽然没有“不要使用相对路径”的错误提示,但是,其实这里的LOG4C_VENDOR_DIR 的值已经不是我们想要的路径了,因为之前执行了 cd $(LOG4C_DIR) 的动作,`pwd`得到的已经不是log4c-test工程的根目录了,而是log4c-test工程的根目录下的 log4c-1.2.4 子目录,于是make install 把文件都拷贝到了 log4c-1.2.4/vendors/log4c 下面!
LOG4C_VENDOR_DIR = `pwd`/vendors/log4c
cd $(LOG4C_DIR) && ./configure --prefix=$(LOG4C_VENDOR_DIR) && make && make install
4)当然也可以只make而不make install,只要指定正确的log4c include和log4c lib路径就可以了,其实这样貌似还简单些~