来自 C 中存档 (.a) 文件的共享库
Shared library from archive (.a) file in C
我的任务是从对象文件创建归档文件 .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.");
}
main.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
有人请指出我哪里错了吗?非常感谢。
问题是你的错误:不要从存档中创建共享库,而是从对象中创建共享库,即像这样更改 Makefile
libfoo.so : foo.o bar.o
$(CC) -shared -o $@ foo.o bar.o
你也可以用%.o
表示所有对象
你还需要 CFLAGS = -fPIC
全局影响编译命令,而不仅仅是 link 步骤,也就是说你的 .o 目标文件应该是位置无关的。
这里也不需要extern
,所有的C函数都是隐式extern
extern void foo(void);
我也不建议使用 rpath
和更好的
export LD_LIBRARY_PATH=.
从当前目录加载.so(或.so目录的导出路径)
如果您希望从静态库构建共享库,您必须告诉链接器使用静态库 (.a) 中包含的所有 function/symbols。否则共享库 (.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
我的任务是从对象文件创建归档文件 .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.");
}
main.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
有人请指出我哪里错了吗?非常感谢。
问题是你的错误:不要从存档中创建共享库,而是从对象中创建共享库,即像这样更改 Makefile
libfoo.so : foo.o bar.o
$(CC) -shared -o $@ foo.o bar.o
你也可以用%.o
表示所有对象
你还需要 CFLAGS = -fPIC
全局影响编译命令,而不仅仅是 link 步骤,也就是说你的 .o 目标文件应该是位置无关的。
这里也不需要extern
,所有的C函数都是隐式extern
extern void foo(void);
我也不建议使用 rpath
和更好的
export LD_LIBRARY_PATH=.
从当前目录加载.so(或.so目录的导出路径)
如果您希望从静态库构建共享库,您必须告诉链接器使用静态库 (.a) 中包含的所有 function/symbols。否则共享库 (.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