编译静态库、动态库以及条件编译用法

CC=g++
AR=ar

OBJ_PATH=./objs
CPP_SOURCES = $(wildcard *.cpp)
CPP_OBJS = $(patsubst %.cpp, $(OBJ_PATH)/%.o, $(CPP_SOURCES))

INCDIR= -I/usr/local/freetds0.91/include \
        -I/usr/local/include \
        -I/usr/include \
        -I../../redis-2.6.13/deps

CCFLAG=-g
ifeq ($(MAKECMDGOALS), so)
    CCFLAG= -g -fPIC
endif

ar:init deps $(CPP_OBJS)
	$(AR) -rsv libcomponent.a $(CPP_OBJS)

so:init deps $(CPP_OBJS)
	$(CC) -shared -fPIC -o libcomponent.so $(CPP_OBJS)

init:
	mkdir -p $(OBJ_PATH)

deps:
	cd jsoncpp && make
	cd ../../redis-2.6.13/deps && make hiredis && make jemalloc && make linenoise && make lua
	cd ../../redis-2.6.13/src && make
    
$(CPP_OBJS):$(OBJ_PATH)/%.o:%.cpp
	$(CC) $(CCFLAG) $(INCDIR) -o $@ -c $<

clean:
	rm -rf *.o *.a *.so objs
	cd ../../redis-2.6.13/deps && make distclean
	cd ../../redis-2.6.13/src && make clean

help:
	@echo "make: default compile static lib --libcomponent.a"
	@echo "make so: compile dynamic lib --libcomponent.so"
	@echo "make deps: compile jsoncpp redis"
	@echo "make clean: clean obj lib"


L13——L16:根据编译目标定义不同的编译选项,动态库编译源文件时要添加-fPIC编译选项。

关于-fPIC选项:

不加fPIC编译出来的so,是要再加载时根据加载到的位置再次重定位的.(因为它里面的代码并不是位置无关代码)
如果被多个应用程序共同使用,那么它们必须每个程序维护一份so的代码副本了.(因为so被每个程序加载的位置都不同,显然这些重定位后的代码也不同,当然不能共享)这样就失去了共享库的好处,实际上和静态库的区别并不大,在运行时占用的内存是类似的,仅仅是二进制代码占的硬盘空间小一些.而且在加载时才重定位的开销也很大(这一点使得这种做法更加没有意义).

我们总是用fPIC来生成so,也从来不用fPIC来生成a.
fPIC与动态链接可以说基本没有关系,libc.so一样可以不用fPIC编译,只是这样的so必须要在加载到用户程序的地址空间时重定向所有表目.

因此,不用fPIC编译so并不总是不好.
如果你满足以下4个需求/条件:
1.该库可能需要经常更新
2.该库需要非常高的效率(尤其是有很多全局量的使用时)
3.该库并不很大.
4.该库基本不需要被多个应用程序共享

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值