gcc与静态库链接

时间:2016-09-28 18:36:20

标签: c gcc

我正在读一本名为“GCC简介”的书,想要澄清一下。 一书表示下面的代码会导致错误,但在编译时,构建并运行完美无缺:

#include <math.h>
#include <stdio.h>
int main (void) {
  double x = sqrt (2.0);
  printf ("The square root of 2.0 is %f\n", x);
  return 0;
}

我从书中引用“单独尝试从此源文件创建可执行文件会导致编译器在链接阶段发出错误:

$ gcc -Wall calc.c -o calc
/tmp/ccbR6Ojm.o: In function `main':
/tmp/ccbR6Ojm.o(.text+0x19): undefined reference 
  to `sqrt'

本书提供的解决方案是,您应该包含数学库“ libm.a ”的路径,如下所示:

$ gcc -Wall calc.c /usr/lib/libm.a -o calc

必须指定我们在程序中使用的内置库的路径是非常不方便的。我可以理解将路径添加到我自己的自定义库的原因,但 libm.a 内置于gcc中。虽然这本书很老(2004年出版),更多现代版本的gcc 已经发生了变化,因此我们不需要包含 libm.a

*更新*

我注意到taskinoor给出的答案演示了更新的代码,如果在编译时未知传递给sqrt()的值,则需要使用 -lm 标志。

我使用VS学习了C / C ++,但我现在的目标是学习和使用gcc。我有Visual Studio 2013和VS编译器/链接器似乎不那么挑剔。例如,我可以编译几乎任何简单的程序,而无需指定神秘的编译器标志。

我正在学习KUBUNTU 16.04.1附带的 gcc version 5.4

2 个答案:

答案 0 :(得分:6)

sqrt (2.0);

现代GCC很有能力确定您正在尝试查找常量的平方根,因此它能够在编译时计算出它。您的目标代码不包含对sqrt的实际调用。

如果您使用的是在运行时通过scanf输入的变量,那么它不会在没有libm的情况下进行链接。

int main() {
    double x;

    scanf("%lf", &x);
    printf("%lf\n", sqrt(x));

    return 0;
}

在Ubuntu 14.04上没有libm gcc 4.8.4,结果如下:

/tmp/ccVO2fRY.o: In function `main':
sqrt.c:(.text+0x2c): undefined reference to `sqrt'
collect2: error: ld returned 1 exit status

但如果我像你的例子那样放一个常数而不是x那么它在没有libm的情况下很好地链接。

P.S:我不知道确切的版本,因为GCC能够做到这一点。希望其他人可以指出这一点。

答案 1 :(得分:2)

我注意到在某些操作系统上,没有显式链接就可以使用公共库。特别是,我经常采用一个最初在我的Mac上开发的工作C项目,并且在我明确链接到我使用的库(如libm)之前,该项目不会在Linux上编译。

当然,这通常用于动态链接而不是静态链接......