【问题标题】:Shared library disparity between Linux CentOS 7 and Ubuntu 20.04.1 LTSLinux CentOS 7 和 Ubuntu 20.04.1 LTS 之间的共享库差异
【发布时间】:2021-06-09 00:13:16
【问题描述】:

我正在将一个用 C 编写的项目从 CentOS 7(Core)移植到 Ubuntu 20.04.1 LTS(Focal Fossa)系统。该项目严重依赖<cpuset.h> 库,并在CentOS 系统上正确编译和执行。但是,当我尝试在 Ubuntu 系统上使用 cpuset.h 中的函数时,我收到“未定义引用”错误。

以下代码,存储在文件test.c 中,可在 CentOS 上正确编译和运行:

#define _GNU_SOURCE

#include<stdio.h>
#include <cpuset.h>

int main(){

    int x = cpuset_version();
    printf("cpuset lib version: %d\n",x );

    return 0;
}

我如何编译: gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test

输出:

[xxxx@CentOS]$ ./test 
cpuset lib version: 3

但是,当我尝试在 Ubuntu 系统上编译相同的 test.c 文件时,我收到此错误:

xxxx@Ubuntu:$ gcc -Wall -O2 -std=gnu99 -g -lcpuset test.c -o test
/usr/bin/ld: /tmp/ccpxlk4F.o: in function `main':
test.c:8: undefined reference to `cpuset_version'
collect2: error: ld returned 1 exit status

此外,这不仅限于&lt;cpuset.h&gt; 库。我尝试使用&lt;pthread.h&gt; 中的一个简单函数,它也给了我同样的错误。任何人都可以帮助确定为什么我不能在 Ubuntu 系统上使用共享库吗?提前致谢

【问题讨论】:

  • 这是您上一个问题的后续问题:stackoverflow.com/questions/66535986/… 但是,它看起来像回归。在上一个问题中,您可以链接到库[并且错误是来自cpuset_create 调用的运行时错误]。现在,您在链接到库时遇到了问题。但是,由于它可以编译,这意味着cpuset.h 存在并且可以访问。那么,什么目录呢?对于 pthread,您是否将 -lpthread 添加为 last 参数。尝试使用find:(例如)find / -xdev -name '*pthread*' [也适用于*cpuset*]
  • 按命令行的顺序扫描事物。将 -lcpuset 作为 last 参数。正如你所拥有的,lib is 被扫描,但没有被拉入,因为它只会在 编译 test.c没有 之后这样做i> 在扫描 -lcpuset 时发生。
  • @CraigEstey:没错!所以,Shivam Kundan,使用gcc -Wall -O2 -std=gnu99 -g test.c -lcpuset -o test。在 Makefile 术语中,$(CC) $(CFLAGS) -c $^ 编译但不链接,$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@ 链接(或编译和链接,就像现在一样)。
  • 这在 CentOS 上也会失败。
  • 感谢您的帮助,@CraigEstey。解决方案确实是将 -lcpuset 移动到命令的末尾。由于这与我之前的帖子无关,因此我将其标记为已回答。

标签: c linux ubuntu shared-libraries centos7


【解决方案1】:

由于 OP 的问题是 GCC 的参数顺序错误(许多指南确实显示了错误的顺序!),正如问题的 cmets 中所讨论的,我相信显示一个最小的 Makefile 来处理这些是有保证的:

CC      := gcc
CFLAGS  := -Wall -O2 -g
LDFLAGS := -lcpuset
TARGETS := test

.PHONY: all clean

all: $(TARGETS)

clean:
    rm -f *.o $(TARGETS)

%.o: %.c
    $(CC) $(CFLAGS) -c $^

test: test.o
    $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@

请注意,Makefile 中的缩进必须使用 Tab 而不是空格。由于本论坛将 Tabs 转换为空格,因此您需要修复上述 makefile,例如通过运行 sed -e 's|^ *|\t|' -i Makefile

如果你想直接将foo.c 编译成可执行文件,方法是

foo: foo.c
    $(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@

只需要运行make(默认使用当前目录下的Makefile,默认target是第一个,在all之上),重新编译TARGETS(这里是@987654328 @,但您可以通过将它们以空格分隔的方式添加到行中来提供更多内容)。

你也可以运行make clean test从“scratch”重建test,即先删除所有临时文件和所有目标。

您可以覆盖CFLAGS 等变量,只需在命令行中提供它们即可;例如,make CFLAGS="-Wall -Wextra -Os" clean all 使用不同的编译标志重新编译所有内容。

【讨论】:

    猜你喜欢
    • 2019-07-22
    • 1970-01-01
    • 2011-03-11
    • 2021-01-14
    • 2017-06-12
    • 1970-01-01
    • 2021-06-05
    • 2021-04-12
    • 1970-01-01
    相关资源
    最近更新 更多