动态库调用另外一个静态库:
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
CFLAGS:=-fPIC
LDFLAGS:=-shared -fpic
SOURCE:=$(wildcard *.cpp)
OBJS:=$(patsubst %.cpp,%.o,$(SOURCE))
TARGET_LIB:=liblive.so
INC = -I../librtmp
all:$(OBJS)
echo $(OBJS)
$(LD) $(LDFLAGS) -o $(TARGET_LIB) $(OBJS) ../librtmp/librtmp.a
%.o:%.cpp
@echo Compiling $< ...
$(CC) -c $(CFLAGS) $(INC) $< -o $*.o
.PHONY: clean
clean:
rm *.so *.o -rf
静态库调用另外一个静态库:
编译liblive.a,liblive.a依赖于librtmp.a.
CC = gcc
CFLAGS := -Wall -O3 -std=c99 -fPIC
MAKEFILEPATH = $(shell pwd)
# rtmp 头文件和lib路径
RTMP_INC_ROOT = $(MAKEFILEPATH)/../librtmp
RTMP_LIB_ROOT = $(MAKEFILEPATH)/../librtmp
#@OBJS = GenDll.o #.o文件与.cpp文件同名
SOURCE:=$(wildcard *.cpp)
OBJS:=$(patsubst %.cpp,%.o,$(SOURCE))
$(warning $(OBJS))
LIB = liblive.a
OPENCV_INC= -I$(RTMP_INC_ROOT)
INCLUDE_PATH = $(OPENCV_INC)
$(warning $(INCLUDE_PATH))
LIB_PATH = -L$(RTMP_LIB_ROOT)
# 依赖的lib名称
RTMP_LIB = $(RTMP_LIB_ROOT)/librtmp.a
all : $(LIB)
# 2. 生成.o文件
%.o : %.cpp
$(CC) $(CFLAGS) -c $< -o $@ $(INCLUDE_PATH) $(LIB_PATH) $(RTMP_LIB)
# 3. 生成静态库文件
$(LIB) : $(OBJS)
rm -f $@
ar cr $@ $(OBJS) $(RTMP_LIB)#这里虽然把他打包进去了,但是我后面用编译一个.so来调用这个liblive.a,发现里面librtmp的库里面的函数是没有定义的,要解决这个问题的话,需要在.so里面在把librtmp.a包含进去,但是这只是下下策。
rm -f $(OBJS)
tags :
ctags -R *
# 4. 删除中间过程生成的文件
clean:
rm -f $(OBJS) $(TARGET) $(LIB)
编译一个librts.so来调用liblive.a
根据第二步编译liblive.a的时候可以看到ar命令是打包了librtmp.a,上面也说了,其实并没有起作用,所以上面ar打包时候把librtmp.a去掉也是一样的,然后在这里编译的时候带上librtmp.a,这样的话层次结构其实并没有出来,哪位大侠知道的话可以留言指导下。
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)ld
MAKEFILEPATH = $(shell pwd)
$(warning $(MAKEFILEPATH))
CFLAGS:=-fpic
LDFLAGS:=-shared -fpic
SOURCE:=$(wildcard *.c)
OBJS:=$(patsubst %.c,%.o,$(SOURCE))
TARGET_LIB:=librts.so
INC:=-I$(MAKEFILEPATH)/../thirdlibs/include -I$(MAKEFILEPATH)/../thirdpart/live/LivePlay
LIBDIR:=$(MAKEFILEPATH)/../thirdlibs/lib
LIVEDIR:=$(MAKEFILEPATH)/../thirdpart/live
LIBS:= $(LIBDIR)/libstrophe.so $(LIVEDIR)/LivePlay/liblive.a $(LIVEDIR)/librtmp/librtmp.a -lm -lpthread
all:$(OBJS)
echo $(OBJS)
$(LD) $(LDFLAGS) -o $(TARGET_LIB) $(OBJS) $(LIBS)
%.o:%.c
@echo Compiling $< ...
$(CC) -c $(CFLAGS) $(INC) $< -o $*.o
.PHONY: clean
clean:
rm *.so *.o -rf
最后可以编写一个可执行程序来调用了,-Wl,-rpath=这个是指定一个运行时候的搜索路径,作用和环境变量一样
CC=gcc
CFLAGS=-Wall -std=c99
TARGET=main
SRCS = main.c
INC = -I./thirdlibs/include -I./thirdpart/live/LivePlay
LDFLAGS += -L./thirdlibs/lib/ -L./src -Wl,-rpath=./thirdlibs/lib -Wl,-rpath=./src
DLIBS = -lrts -lstrophe
OBJS = $(SRCS:.c=.o)
CFLAGS += $(INC) #header files
$(TARGET):$(OBJS)
$(CC) -g -o $@ $^ $(LDFLAGS) $(DLIBS)
clean:
rm -rf $(TARGET) $(OBJS)
%.o:%.c
$(CC) $(CFLAGS) -g -o $@ -c $<
关于configure的一些事情
编译libexpat
CFLAGS="-fPIC"这个很重要,你不添加这个编译出来的动态库没有问题,但是静态库就会出问题,什么问题呢,举个例子,如果你编写一个so来调用这个.a,就会提示 relocation R_X86_64_32 against `.rodata' can not be used when making a shared object;这种错误,所以一定记得加上。
CFLAGS="-fPIC" ./configure --prefix=/home/vmuser/ljt/rts_linux/thirdlibs
openssl编译
./config shared -fPIC --prefix=/home/vmuser/ljt/rts_linux/thirdlibs 如果是arm的话记得加上no-asm,详细见上一篇博客。这里也同样记得加上-fPIC。
libstrophe编译
1.依赖的库为静态库应该这么写,.a的一律写绝对路径,然后LIBS是依赖的系统库,这样编译出来的libstrophe.a直接就包含了libssl.a等.a库,当其他程序调用libstrophe.a的时候就不需要再把libssl.a包含进去,这比上面那个liblive.a要先进了,具体怎么做到的我还是没有明白。
expat_CFLAGS=-I/home/vmuser/ljt/rts_linux/thirdlibs/include expat_LIBS='/home/vmuser/ljt/rts_linux/thirdlibs/lib/libexpat.a' openssl_CFLAGS=-I/home/vmuser/ljt/rts_linux/thirdlibs/include openssl_LIBS='/home/vmuser/ljt/rts_linux/thirdlibs/lib/libssl.a /home/vmuser/ljt/rts_linux/thirdlibs/lib/libcrypto.a' LIBS=-ldl CFLAGS="-fPIC" ./configure --prefix=/home/vmuser/ljt/rts_linux/thirdlibs/
2.如果依赖的库为动态库应该这么写,LIBS选项都可以不要,很奇怪吧,呵呵。
openssl_CFLAGS=-I/home/vmuser/ljt/rts_linux/thirdlibs/include openssl_LIBS='-L/home/vmuser/ljt/rts_linux/thirdlibs/lib -lssl -lcrypto' expat_CFLAGS=-I/home/vmuser/ljt/rts_linux/thirdlibs/include expat_LIBS='-L/home/vmuser/ljt/rts_linux/thirdlibs/lib -lexpat' ./configure --prefix=/home/vmuser/ljt/rts_linux/thirdlibs/