Linux下cmake什么时候需要链接系统so,什么时候不需要?

在尝试使用cmake编译代码。
在写CMakeLists的时候发现例如sqrt这样的函数,在libm.so中,就需要在编译的时候链接。
但是像malloc、memset、free这样的函数就不用链接动态库。
请问这其中有什么规律吗?

阅读 5.3k
3 个回答

你说的malloc、memset、free都是属于C标准库的,gcc会帮我们链接,但是sqrt属于数学库不属于标准库,所以需要手动-lm,写个Hello World,然后-v编译下:

$ gcc -v hello.c

最后几行就可以看到到底链接了什么:

/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/collect2 --build-id --no-add-needed --eh-frame-hdr --hash-style=gnu -m elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crti.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtbegin.o -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64 -L/lib/../lib64 -L/usr/lib/../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../.. /tmp/cc18ZA1j.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-redhat-linux/4.8.5/crtend.o /usr/lib/gcc/x86_64-redhat-linux/4.8.5/../../../../lib64/crtn.o

或者 ldd a.out可以看程序链接了哪些动态库

[root]$ ldd a.out 
    linux-vdso.so.1 =>  (0x00007ffd2e153000)
    libc.so.6 => /lib/libc.so.6 (0x00007f912499a000)    
    /lib64/ld-linux-x86-64.so.2 (0x00007f9124d83000)

在写CMakeList时,由于像malloc printf这类函数,都是属于标准库的函数,在好多linux系统中已经将其默认的链接进去,所以在写时并不需要我们手动进行链接,但是math库并不是一个标准库,linux系统并没有默认的链接这个库文件,因此你需要手动显式的进行链接。

math.h里的函数需要libm,486以前CPU不集成协处理器,有的机器会没有协处理器,这时浮点运算需要软件模拟。为了节约内存和链接时间,所以早期编译软件包括Turbo C都把不常用的数学运算单独做一个模块,不用浮点运算就不需要它了,甚至可能在libm里实现了支持浮点版本的printf。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题