cygwin中动态库链接的问题

问题的出现

(这里解释得比较累赘, 要找到答案, 可以直接进入第二章节)

看书(Ruminations on C++)时, 以章节为单位写了一些独立的小程序(使用cygwin g++作为编译器, sublime text 2作为编辑器). 以下是目录结构, 后来将写日志的函数提取出来, 放到common/common.h(.cpp), 并生成libcommon.so动态库, 供其他程序调用.

MJN@MJN-THINK ~/src/ruminations_on_c++
$ ls -1
05_surrogate_classes
06_handles_part1
07_handles_part2
08_an_object_oriented_program
09_analysis_of_classroom_exercise_part1
common

我使用的makefile的公共代码来自于$HOME/make/make.inc, 其大概内容如下:

[plain]  view plain copy print ?
  1. include ${HOME}/src/make/make.local  
  2.   
  3. include_dirs=${HOME}/src/ruminations_on_c++/common  
  4. lib_dirs=${HOME}/src/ruminations_on_c++/common  
  5.   
  6. #------------------------------------------------  
  7. # c compiler  
  8. #------------------------------------------------  
  9. Linux_CC  = gcc  
  10. AIX_CC    = cc  
  11. SunOS_CC  = CC  
  12.   
  13. #------------------------------------------------  
  14. # c compiler flags  
  15. #------------------------------------------------  
  16. Linux_CCFLAGS = -std=c99 -g -Wall   
  17. AIX_CCFLAGS   = -g -q$(OBJECT_MODE) -D_BIG_ENDIAN_ -D$(OBJECT_MODE_BIT)  
  18. SunOS_CCFLAGS =   
  19.   
  20. #------------------------------------------------  
  21. # c++ compiler  
  22. #------------------------------------------------  
  23. Linux_CXX = g++  
  24. AIX_CXX   = xlC  
  25. SunOS_CXX = CC  
  26.   
  27. #------------------------------------------------  
  28. # DLL CC  
  29. #------------------------------------------------  
  30. AIX_DLLCC = ar -X$(OBJECT_MODE) rv  
  31.   
  32. #------------------------------------------------  
  33. # DLL CC1  
  34. #------------------------------------------------  
  35. Linux_DLLCC1 = ar rvs -o   
  36. AIX_DLLCC1 = xlC -q$(OBJECT_MODE) -brtl -qmkshrobj -o   
  37.   
  38. AIX_DLLSUFFIX = so  
  39.   
  40. #------------------------------------------------  
  41. # c++ compiler flags  
  42. #------------------------------------------------  
  43. Linux_CXXFLAGS = -g -Wall  
  44. AIX_CXXFLAGS    =   
  45. SunOS_CXXFLAGS  =   
  46.   
  47. #------------------------------------------------  
  48. # real variable  
  49. #------------------------------------------------  
  50.   
  51. CC       = $($(OSTYPE)_CC)  
  52. CXX      = $($(OSTYPE)_CXX)  
  53. CCFLAGS  = $($(OSTYPE)_CCFLAGS)  
  54. CXXFLAGS = $($(OSTYPE)_CXXFLAGS) -I$(include_dirs)   
  55. DLLCC    = $($(OSTYPE)_DLLCC)  
  56. DLLCC1   = $($(OSTYPE)_DLLCC1)  
  57. DLLSUFFIX = $($(OSTYPE)_DLLSUFFIX)  
  58.   
  59. #clear old suffixes  
  60. .SUFFIXES:  
  61. .SUFFIXES: .c .cpp .o .exe  
  62.   
  63. .cpp.o:  
  64.     $(CXX) -c -o $*.o $< $(CXXFLAGS)  
  65.   
  66. .cpp.exe:  
  67.     $(CXX) -c -o $*.o $< $(CXXFLAGS)  
  68.     $(CXX) -o $* $(objs) $*.o $(CXXFLAGS) -L$(lib_dirs) -lcommon  
  69.   
  70. .PHONY: clean all build  
  71.   
  72. clean:  
  73.     rm -f *.o  
  74.     for i in `echo $(exes) | sed s/.exe//g`; \  
  75.     do \  
  76.         rm -f $$i; \  
  77.     done  

common目录的内容很简单:

MJN@MJN-THINK ~/src/ruminations_on_c++/common
$ ls
common.cpp  common.h  makefile

commcon/makefile的大概内容

[plain]  view plain copy print ?
  1. MJN@MJN-THINK ~/src/ruminations_on_c++/common  
  2. $ cat makefile  
  3. include ${HOME}/src/make/make.inc  
  4.   
  5. objs = common.o  
  6.   
  7. all: $(objs)  
  8.   
  9. dll: all  
  10.         g++ -shared -o libcommon.so $(objs)  
现在进入目录08_an_object_oriented_program, 其源文件为:

MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program
$ ls
Binary_node.cpp  Expr.cpp          main.cpp          Unary_node.cpp
Binary_node.h    Expr.h            makefile          Unary_node.h
Exp_node.cpp     Integer_node.cpp  Ternary_node.cpp  UseCount.cpp
Exp_node.h       Integer_node.h    Ternary_node.h    UseCount.h

makefile大概内容如下

[plain]  view plain copy print ?
  1. MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program  
  2. $ cat makefile  
  3. include ${HOME}/src/make/make.inc  
  4.   
  5. objs = Integer_node.o Unary_node.o Binary_node.o Expr.o UseCount.o Ternary_node.o  
  6.   
  7. exes = main.exe  
  8.   
  9. all: $(objs)  
  10.   
  11. build: $(exes)  

现在尝试编译出libcommon.so:

MJN@MJN-THINK ~/src/ruminations_on_c++/common
$ make dll
g++ -c -o common.o common.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -shared -o libcommon.so common.o

编译08_an_object_oriented_program目录下的代码:

MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program
$ make all && make build
g++ -c -o Integer_node.o Integer_node.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -c -o Unary_node.o Unary_node.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -c -o Binary_node.o Binary_node.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -c -o Expr.o Expr.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -c -o UseCount.o UseCount.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -c -o Ternary_node.o Ternary_node.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -c -o main.o main.cpp -g -Wall -I/home/MJN/src/ruminations_on_c++/common
g++ -o main Integer_node.o Unary_node.o Binary_node.o Expr.o UseCount.o Ternary_node.o main.o -g -Wall -I/home/MJN/src/ruminations_on_c++/common  -L/home/MJN/src/ruminations_on_c++/common -lcommon
/usr/lib/gcc/i686-pc-cygwin/4.7.3/../../../../i686-pc-cygwin/bin/ld: cannot find -lcommon
collect2: 错误:ld 返回 1
/home/MJN/src/make/make.inc:67: recipe for target 'main.exe' failed
make: *** [main.exe] Error 1

在链接的时候, 找不到动态库libcommon.so

解决方案

使用静态库(寻找替代方案)

静态编译libcommon.a:

MJN@MJN-THINK ~/src/ruminations_on_c++/common
$ ar rvs -o libcommon.a common.o
ar: 正在创建 libcommon.a
a - common.o
MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program
$ ./main
((-5)*(3+4))=-35
(((-5)*(3+4))*((-5)*(3+4)))=1225
(?:,0,((-5)*(3+4)),(((-5)*(3+4))*((-5)*(3+4))))=1225

将生成的libcommon.a复制到08_an_object_oriented_program目录, 并使用该库链接main:

MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program
$ make build
g++ -c -o main.o main.cpp -g -Wall
g++ -o main Integer_node.o Unary_node.o Binary_node.o Expr.o UseCount.o Ternary_node.o main.o -g -Wall  libcommon.a

程序运行正常.

解决动态库问题方法一: .so改为.dll

链接的时候, cygwin会找后缀为.dll(windows中的动态库后缀)的动态库, 生成动态库的时候, 文件名后缀改为.dll, 或者建立到libcommon.so的软链接libcommon.dll

MJN@MJN-THINK ~/src/ruminations_on_c++/common
$ ln -s libcommon.so libcommon.dll

可以正常地链接:

MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program
$ make build
g++ -c -o main.o main.cpp -g -Wall
g++ -o main Integer_node.o Unary_node.o Binary_node.o Expr.o UseCount.o Ternary_node.o main.o -g -Wall  -L/home/MJN/src/ruminations_on_c++/common -lcommon

MJN@MJN-THINK ~/src/ruminations_on_c++/08_an_object_oriented_program
$ ./main
/home/MJN/src/ruminations_on_c++/08_an_object_oriented_program/main.exe: error while loading shared libraries: libcommon.so: cannot open shared object file: No such file or directory

但是在运行的时候, 程序找不到动态库. 这里有一个很关键的一点, 就是一定要把动态库目录放到$PATH环境变量中, 不然运行的时候无法找到动态库:

[html]  view plain copy print ?
  1. #.bash_profile  
  2. export PATH=$PATH:$HOME/src/ruminations_on_c++/common  
重新登录shell, 使环境变量生效, 运行main就正常了.

解决动态库问题方法二: 使用动态库的全名

链接动态库的时候, 使用全名:

[plain]  view plain copy print ?
  1. .cpp.exe:  
  2.     $(CXX) -c -o $*.o $< $(CXXFLAGS)  
  3.     $(CXX) -o $* $(objs) $*.o $(CXXFLAGS) -L$(lib_dirs) -l:libcommon.so  
这样就可以正确链接了.

但是在执行前, 也一定要把动态库目录放到$PATH环境变量中, 不然运行的时候无法找到动态库.

参考: 

[1] stackoverflow: cygwin g++ Linker doesn't find shared library

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值