linux g++编译以及库多重依赖

目录

一、编译命令

二、编译相关选项

三、静态库和动态库的编译命令

1、生成动态库和静态库

2、-fPIC选项

3、如何解决运行时找不到链接库的问题

四、库多重依赖

1、动态库依赖动态库

2、动态库依赖静态库

3、静态库依赖静态库


一、编译命令

g++ –c Hello.cpp  编译文件,生成目标文件Hello.o

g++ Hello.o –o a.out  链接并重命名为可执行文件a.out

g++ Hello.cc    编译链接一起,生成a.out

g++ Hello.cc –o hello 生成a.out并命名为hello

二、编译相关选项

(1)-c

生成.o文件,对代码文件进行预处理、编译和汇编,相当于windows下生成目标文件obj

g++ -c hello.cpp

(2)-I DirPath

指定包含文件

-include file

-i file

指定包含目录

-I path

g++ hello.cpp -include ../include/a.h

-I- DirPath

就是取消前一个参数的功能,所以一般在-I DirPath之后使用

(3)-L LibPath

指定链接库的路径

-l LibraryPath

指定链接库

-llibrary

(4)  -g   
在编译的时候,产生调试信息,程序运行时可以dbg调试

(4)-static

此选项将禁止使用动态库。

优点:程序运行不依赖于其他库

缺点:文件比较大

gcc test_main.c -static -o test_main -lpthread

会发现test_main很大,它已经把各种依赖的东西都包含进来

(5) -shared (-G)

此选项将尽量使用动态库,为默认选项

优点:生成文件比较小

缺点:运行时需要系统提供动态库

(6)-Wall

一般使用该选项,允许发出GCC能够提供的所有有用的警告。也可以用-W{warning}来标记指定的警告。

三、静态库和动态库的编译命令

1、生成动态库和静态库

(1)得到hello.o

g++ -c hello.cpp

(2)得到静态库myhello.a

ar -cr libmyhello.a hello.o

(3)使用静态库

g++ -o hello main.c -L ./ -lmyhello

-L ./表示静态库位于当前目录下,myhello自动加上lib组成静态库名称libmyhello.a

(4)得到动态库myhello.so

 g++ -fPIC -shared hello.cpp -o libmyhello.so

(5)使用动态库

动态库的时候和静态库使用一样,唯一值得注意的是当目录中同时存在相同名称的动态库和静态库时,编译的时候优先使用动态库

2、-fPIC选项

加上-fPIC选项生成的动态库时位置无关的,可以实现多个进程共享动态库,多个进程引用同一个PIC动态库时,可以共享内存。这一个库在不同进程中的虚拟地址不同,但操作系统显然会把它们映射到同一块物理内存上。

不加fPIC,则加载so文件时,需要对代码段引用的数据对象需要重定位,重定位会修改代码段的内容,这就造成每个使用这个.so文件代码段的进程在内核里都会生成这个.so文件代码段的copy.每个copy都不一样,取决于这个.so文件代码段和数据段内存映射的位置。可见,这种方式更消耗内存。

3、如何解决运行时找不到链接库的问题

(1)将链接库添加到系统默认的搜索路径下,如/lib、/usr/lib

(2)设置临时动态库路径的环境变量,这种方法设置的是临时的,系统重启之后就没了

export LD_LIBRARY_PATH=./

取消设置

export LD_LIBRARY_PATH=

(3)/etc/ld.so.cache中缓存了动态库路径,可以通过修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变

(4)编译链接添加-Wl,-rpath命令选项,将运行时动态库的搜索路径记录在可执行程序中

例如,有源文件test.cpp和func.cpp

g++ -shared -fPIC func.cpp -o libfunc.so

编译得到libfunc.so动态库

g++ main.cpp -o a.out -L ./ -lfunc

编译得到a.out,执行a.out,提示出错

ldd查看a.out依赖的动态库,发现libfunc.so找不到

g++ main.cpp -o a.out -L ./ -lfunc -Wl,-rpath ./

编译得到a.out,执行a.out,运行成功,ldd查看a.out依赖的动态库,发现libfunc.so路径正确

把a.out和libfunc.so拷贝到任何目录下,都能运行成功

-Wl:这个是gcc的参数,表示编译器将后面的参数传递给链接器ld。

-rpath:使用man ld命令查看手册,找到了-rpath的讲解:

Add a directory to the runtime library search path. This is used when linking an ELF executable with shared objects. All -rpath arguments are concatenated and passed to the runtime linker, which uses them to locate shared objects at runtime. The -rpath option is also used when locating shared objects which are needed by shared objects explicitly included in the link; see the description of the -rpath-link option. If -rpath is not used when linking an ELF executable, the contents of the environment variable "LD_RUN_PATH" will be used if it is defined.

四、库多重依赖

//world.cpp
#include <stdio.h>

void world(void)
{
    printf("world.\n");
}
//hello.cpp
#include <stdio.h>

void world(void);

void hello(void)
{
    printf("hello\n");
    world();
}
//test.cpp

void hello(void);

int main(void)
{
    hello();
    return 0;
}

1、动态库依赖动态库

动态库hello编译时需要链接world,并需要设置-Wl,-rpath ./

test编译时只需要链接hello,并需要设置-Wl,-rpath ./

(1)编译word动态库

g++ -shared -fPIC world.cpp -o libworld.so

(2)编译hello动态库

g++ -shared -fPIC hello.cpp -o libhello.so

ldd libhello.so

查看libhello.so的依赖库,没有看到依赖libword.so

g++ -shared -fPIC hello.cpp -o libhello.so -L ./ -lworld

ldd libhello.so

再次查看libhello.so的依赖库,看到了依赖库libword.so,但显示not found

g++ -shared -fPIC hello.cpp -o libhello.so -L ./ -lworld -Wl,-rpath ./

(3)编译可执行文件test

g++ test.cpp -o a.out -L ./ -lhello -lworld -Wl,-rpath ./

编译通过,得到可执行文件a.out,运行成功

2、动态库依赖静态库

静态库world编译也需要设置-fPIC选项

动态库hello需要链接world,但是不需要添加-Wl,-rpath选项

(1)编译word静态库

g++ -c world.cpp

ar -cr libworld.a world.o

(2)编译hello动态库

g++ -shared -fPIC hello.cpp -o libhello.so -L ./ -lworld

编译报错,因为world也必须使用-fPIC,重新编译

(3)编译可执行文件

g++ test.cpp -o a.out -L ./ -lhello -Wl,-rpath ./

3、静态库依赖静态库

一种方法是,  hello和world静态库都独立编译,编译test时链接两个静态库,被调用库调用顺序靠后。静态库依赖有顺序,动态库没有。

另一种方法是,编译hello静态库时,将hello.o和world.o都包含进去。

(1)编译world静态库

g++ -c world.cpp

ar -cr libworld.a world.o

(2)编译hello静态库

g++ -c hello.cpp

ar -cr libhello.a hello.o

(3)编译可执行文件

g++ test.cpp -o a.out -L ./ -lworld -lhello

因为静态库的依赖有顺序,被调用库应该放在调用库后面,动态库没有依赖顺序,正确输入如下

g++ test.cpp -o a.out -L ./ -lhello -lworld

 (4)静态库包含静态库

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值