【问题标题】:Shared library from archive (.a) file in CC 中归档 (.a) 文件中的共享库
【发布时间】:2015-04-11 23:07:19
【问题描述】:

我的任务是从对象文件创建存档文件 .a 并从存档 .a 文件创建共享库文件。我尝试使用以下文件进行实验:
foo.h

#ifndef _foo_h__
#define _foo_h__
extern void foo(void);
extern void bar(void); 
#endif //_foo_h__


foo.c

#include<stdio.h>

void foo(void)
{
    puts("Hello, I'm a shared library");
}


bar.c

#include<stdio.h>

void bar(void)
{
    puts("This is bar function call.");
}


ma​​in.c

#include <stdio.h>
#include"foo.h"

int main(void)
{
    puts("This is a shared library test...");
    foo();
    bar();
    return 0;
}


制作文件

CFLAGS = -Wall -Werror
LDFLAGS = -L/home/betatest/Public/implicit-rule-archive -Wl,-rpath,'$$ORIGIN'

all : run

run : main.o libfoo.so
    $(CC) $(LDFLAGS) -o $@ $^

libfoo.so : CFLAGS += -fPIC # Build objects for .so with -fPIC.
libfoo.so : libfoo.a
    $(CC) -shared -o $@ $^

libfoo.a : foo.o bar.o
    ar cvq libfoo.a foo.o bar.o
#   ar cr libfoo.a foo.o bar.o

# Compile any .o from .c. Also make dependencies automatically.
%.o : %.c
    $(CC) -c $(CFLAGS) -o $@ $<

#Include dependencies on subsequent builds.

.PHONY : all clean

clean :
    -rm -f *.o *.d run libfoo.*

这个简单的测试程序似乎运行良好,但在编译时使用 make 它产生错误:

cc -c -Wall -Werror -o main.o main.c
cc -c -Wall -Werror -fPIC  -o foo.o foo.c
cc -c -Wall -Werror -fPIC  -o bar.o bar.c
ar cvq libfoo.a foo.o bar.o
a - foo.o
a - bar.o
cc -shared -o libfoo.so libfoo.a
cc -L/home/betatest/Public/implicit-rule-archive -Wl,-rpath,'$ORIGIN' -o run main.o libfoo.so
main.o: In function `main':
main.c:(.text+0xf): undefined reference to `foo'
main.c:(.text+0x14): undefined reference to `bar'
collect2: ld returned 1 exit status
Makefile-test:7: recipe for target 'run' failed
make: *** [run] Error 1

有人请指出我哪里出错了?非常感谢。

【问题讨论】:

  • 你没有链接共享库:试试-lfoo而不是libfoo.so
  • cc 在 $ORIGIN 周围得到文字单引号。尝试省略它们。

标签: c linux makefile shared-libraries


【解决方案1】:

如果您希望从静态库构建共享库,您必须告诉链接器使用静态库 (.a) 中包含的所有函数/符号。否则,共享库 (.so) 中不会包含任何内容。

您必须在链接中使用--whole-archive/--no-whole-archive 对。

CFLAGS = -Wall -Werror
LDFLAGS = -L/home/betatest/Public/implicit-rule-archive -Wl,-rpath,'$$ORIGIN'

all : run

run : main.o libfoo.so
    $(CC) $(LDFLAGS) -o $@ $^

libfoo.so : CFLAGS += -fPIC # Build objects for .so with -fPIC.
libfoo.so : libfoo.a
    $(CC) -shared -o $@ -Wl,--whole-archive $^  -Wl,--no-whole-archive

libfoo.a : foo.o bar.o
     ar cvq libfoo.a foo.o bar.o

# Compile any .o from .c. Also make dependencies automatically.
%.o : %.c
    $(CC) -c $(CFLAGS) -o $@ $<

#Include dependencies on subsequent builds.

.PHONY : all clean

clean :
    -rm -f *.o *.d run libfoo.*

您可以使用nm 命令检查导出的函数:

$ nm -D libfoo.so | grep  ' T '
0000000000000702 T bar
0000000000000714 T _fini
00000000000006f0 T foo
0000000000000590 T _init

当没有使用 --whole-archive/--no-whole-archive 对时,您会得到:

$ nm -D libfoo.so | grep  ' T '
0000000000000714 T _fini
0000000000000590 T _init

【讨论】:

  • 谢谢@ctheo 先生!!!!!!编译顺利,编译输出为:cc -c -Wall -Werror -o main.o main.c ; cc -c -Wall -Werror -fPIC -o foo.o foo.c ; cc -c -Wall -Werror -fPIC -o bar.o bar.c ; ar cvq libfoo.a foo.o bar.o ; a - foo.o ; a - bar.o ; cc -shared -o libfoo.so -Wl,--whole-archive libfoo.a -Wl,--no-whole-archive ; cc -L/home/betatest/Public/implicit-rule-archive -Wl,-rpath,'$ORIGIN' -o run main.o libfoo.so ;我想问一下main.o是怎么生成的,是下面定义的隐式规则还是模式?谢谢!!
  • main.o 由cc -c -Wall -Werror -o main.o main.c 命令构建。它使用没有-fPIC 添加的CFLAGS,因为libfoo.so 不依赖它。
  • 这意味着它看到一个依赖 main.o 并调用定义的模式规则 %.o : %.c 。谢谢
【解决方案2】:

您的错误在于问题:不要从存档中创建共享库,而是从对象中创建共享库,即像这样更改 Makefile

libfoo.so : foo.o bar.o
    $(CC) -shared -o $@ foo.o bar.o

您也可以使用%.o 表示所有对象

您还需要全局CFLAGS = -fPIC,以影响编译命令,不仅是链接步骤,即您的 .o 目标文件应该与位置无关。

这里也不需要extern,所有的C函数都是隐式extern

extern void foo(void);

我也不推荐使用rpath 和更好的

export LD_LIBRARY_PATH=.

从当前目录加载.so(或导出到.so目录的路径)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2010-12-25
    相关资源
    最近更新 更多