在大型的项目中,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中。为了方便调用其他文件夹中的文件,最通用的方法就是将一些文件编译成静态的库或动态库,这样在包含其他文件夹的头文件时可以更加简便。
1.编译静态库与动态库
原目录结构:
bin :存放可执行文件
build:存放编译生产的二进制文件(xx.o)
include:存放程序编译时需要调用的头文件(xx.h)
lib:存放程序链接时(生成可执行文件)依赖的静态库或动态库
source:主要存放需要生成静态库和动态库的(*.cpp *.h)文件
本例子是将test.cpp 生成静态库(libtest.a)和动态库(libtest.so)
它们是由source中的makefile自动生成的,其中test.cpp的路径为/home/xqs/testlib,下面看makefile:
1 LIB_NAME ?= test
2
3 PWD :=/home/xqs/testlib
4 BUILD_PATH := $(PWD)/build
5 STATIC_NAME ?= lib$(LIB_NAME).a
6 SHARE_NAME ?= lib$(LIB_NAME).so
7
8 TARGET_PATH := $(PWD)/lib
9 STATIC_TARGET := $(TARGET_PATH)/$(STATIC_NAME)
10 SHARE_TARGET := $(TARGET_PATH)/$(SHARE_NAME)
11
12 SOURCE :=$(wildcard *.cpp)
13 OBJS := $(patsubst %.cpp, $(BUILD_PATH)/%.o, $(wildcard *.cpp))
14
15 all:$(STATIC_TARGET) $(SHARE_TARGET)
16
17 #生成静态库 libtest.a
18 $(STATIC_TARGET):$(OBJS)
19 ar cru $(STATIC_TARGET) $(OBJS)
20 ranlib $(STATIC_TARGET)
21
22 #生成动态库 libtest.so
23 $(SHARE_TARGET):$(OBJS)
24 $(CXX) -shared -fPIC -o $(SHARE_TARGET) $(SOURCE)
25
26 #生成二进制文件(*.o)
27 $(OBJS): $(wildcard *.cpp)
28 $(CXX) -c $< -o $@
29
30 clean:
31 rm -rf $(BUILD_PATH)/*.o $(TARGET_PATH)/*.{a,so}
32
33 .PHONY: all clean
make 之后:testlib文件夹的目录结构为:
从上图可以看到:test.o文件在build,libtest.a与libtest.so在lib中
2.外层makefile:生成可执行文件
1 EXE ?= test
2
3 PWD :=/home/xqs/testlib/bin
4 SHARE_EXE ?= share_$(EXE)
5 STATIC_EXE ?= static_$(EXE)
6
7 STATIC_TARGET := $(PWD)/$(STATIC_EXE)
8 SHARE_TARGET := $(PWD)/$(SHARE_EXE)
9
10 INCL := -I./include/
11 LIB := -L./lib/
12 LIB_NAME := test
13
14
15 all:$(STATIC_TARGET) $(SHARE_TARGET)
16
17 $(STATIC_TARGET):
18 $(CXX) main.cpp -o $(STATIC_TARGET) $(INCL) $(LIB) -l$(LIB_NAME)
19
20 $(SHARE_TARGET):
21 $(CXX) main.cpp $(INCL) $(LIB) -l$(LIB_NAME) -o $(SHARE_TARGET)
22
23 static_app:
24 $(CXX) main.cpp $(INCL) $(LIB) -l$(LIB_NAME) -o $(STATIC_EXE)
25
26 shared_app:
27 $(CXX) main.cpp $(INCL) $(LIB) -l$(LIB_NAME) -o $(SHARE_EXE)
28
29 clean:
30 rm -rf $(STATIC_EXE) $(SHARE_EXE)
make 之后,testlib文件夹的结构为:
从上图可以看出:生成的可执行文件在bin文件夹中
3.链接静态库生成可执行文件static_test
需要注意的是:当lib库中既有静态库又有动态库时,生成可执行文件static_test时会自动链接动态库libtest.so,这是不对的,所以在生成static_test可执行文件时先移除掉动态库libtset.so。
4.执行share_test
在运行可执行文件share_test之前,需要指定动态库的位置,否则会出现找不到库文件的错误:error while loading shared libraries: libtest.so: cannot open shared object file: No such file or directory
所以可以导入动态库的路径:
export LD_LIBRARY_PATH=’/home/xqs/testlib/lib/’
或者 如果不指定库的位置,也可以直接将库放到/lib 或者/usr/lib下
5.编译时遇到的一些问题:
-
找不到/usr/bin/ld: cannot find -lc,找不到/usr/bin/ld: cannot find -lm,找不到/usr/bin/ld: cannot find -lstdc++;这主要是由于编译选项中有-static关键字引起的,解决这问题的方法为:
(1)locate libc.*,找到文件的所在目录,如果有libc.so.1等类似文件,进入文件目录,然后ln -s libc.so.1 libc.so
(2)如果还报同样的错误,则进入root用户下,yum install glibc-static,安装静态库
6.编写makefile的一些坑
1.变量的结尾最好不要有空格,在VIM下可以用shift+$检测是不是最后一个字符是变量的结尾
源码下载链接:链接:https://pan.baidu.com/s/1KG0IKvbpZlDgIzNDzByTmQ 提取码:sdzr