如果动态库更新了,一般情况下不需要重新编译生成可执行文件。因为在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是在执行文件中记录对动态库的引用。程序执行时,再去加载动态库文件。如果动态库已经加载,则不必重复加载,从而能节省内存空间。
但是,有一情况下可能需要重新编译生成可执行文件,那就是当动态库的接口发生了变化,比如函数的参数或返回值类型改变了,或者函数被删除或重命名了。这样的话,原来的可执行文件就无法正确动态库中的函数了,可能会出现错误或异常。
假设我们有一个动态库libmath.so,它提供了一个求平方根的函数sqrt。我们有一个程序test.c,它调用了这个函数来计算一个数的平方根。我们可以这样编译和运行这个程序:
gcc test.c -L. -lmath -o test
./test 4
The square root of 4 is 2.
这里-L.表示在当前目录下查找动态库,-lmath表示链接libmath.so这个动态库,-o test表示生成可执行文件test。
现在假设我们对libmath.so这个动态库做了一些修改,比如增加了一个求立方根的函数cbrt,但是没有改变sqrt函数的接口。我们重新编译生成这个动态库:
gcc -fPIC -shared -Wall -o libmath.so math.c
然后我们再次运行test程序,不需要重新编译:
./test 4
The square root of 4 is 2.
可以看到,程序仍然能够正确地运行,因为它只需要调用sqrt函数,而这个函数的接口没有变化。如果我们想要使用新的cbrt函数,我们就需要修改test.c程序,并重新编译生成可执行文件。
所以,结论是:如果动态库更新后,只是增加了一些新的功能,而没有改变原有的接口,那么不需要重新编译生成可执行文件;但是如果动态库更新后,改变了原有的接口,那么就需要重新编译生成可执行文件。
对于静态库,情况不一样。如果静态库更新了,那么使用它的可执行文件就需要重新编译,否则无法使用静态库中的新功能或修复的错误。这是因为静态库在编译时就被链接到目标代码中,程序运行时不再依赖于静态库。