2015-02-11 64 views
2

我得到了一個任務,從對象文件創建歸檔文件.a,並從歸檔.a文件創建共享庫文件。我已經試過有實驗以下文件:
foo.h中來自存檔(.a)文件的共享庫C

#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; 
} 


的Makefile

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

all : run 

run : main.o libfoo.so 
    $(CC) $(LDFLAGS) -o [email protected] $^ 

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

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 [email protected] $< 

#Include dependencies on subsequent builds. 

.PHONY : all clean 

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

這個簡單的測試程序似乎運行正常,但在使用使其產生錯誤的編譯:

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 

有人請指出我在哪裏出錯?非常感謝。

+1

你不鏈接共享庫:嘗試' -lfoo'而不是'libfoo.so' – 2015-02-11 14:29:46

+0

cc正在獲取$ ORIGIN附近的文字單引號。嘗試省略它們。 – 2015-02-11 14:34:48

回答

4

如果您希望從靜態庫構建共享庫,則必須告訴鏈接器使用靜態庫(.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 [email protected] $^ 

libfoo.so : CFLAGS += -fPIC# Build objects for .so with -fPIC. 
libfoo.so : libfoo.a 
    $(CC) -shared -o [email protected] -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 [email protected] $< 

#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 
+0

謝謝@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 /隱式規則歸檔-Wl,-rpath,'$ ORIGIN'-o運行main.o libfoo.so;' 我想問一下main.o是如何產生的隱式規則或模式定義如下?謝謝!! – 2015-02-11 17:54:00

+0

main.o是由命令'cc -c -Wall -Werror -o main.o main.c'構建的。它使用不帶'-fPIC'的CFLAGS,因爲'libfoo.so'不依賴於它。 – ztik 2015-02-12 08:05:53

+1

它意味着它看到一個依賴main.o並調用定義的模式規則'%.o:%.c'。謝謝 – 2015-02-12 09:02:18

1

你錯就錯在這個問題:不要歸檔使共享庫,從對象組成的,即改變的Makefile這樣

libfoo.so : foo.o bar.o 
    $(CC) -shared -o [email protected] foo.o bar.o 

你也可以使用%.o意味着所有對象

也全局需要CFLAGS = -fPIC,以影響編譯命令,而不僅僅是鏈接步驟,那就是你的.o目標文件應該是位置無關的。

也在這裏extern是不需要的,所有的C函數隱式的extern

extern void foo(void); 

我也不會建議使用rpath更好

export LD_LIBRARY_PATH=. 

從當前目錄加載的.so(或出口指向.so目錄的路徑)