makefile编译静态库与动态库

在大型的项目中,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中。为了方便调用其他文件夹中的文件,最通用的方法就是将一些文件编译成静态的库或动态库,这样在包含其他文件夹的头文件时可以更加简便。
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

  • 3
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值