使用静态库和c ++源代码构建库

时间:2014-08-13 20:36:22

标签: c++ makefile

我有一个用这个makefile编译的静态库(lwip):

CCDEP=g++
CC=g++

#To compile for linux: make ARCH=linux
#To compile for cygwin: make ARCH=cygwin
ARCH=unix
CFLAGS=-g -Wall -D$(ARCH) -DIPv4 -DLWIP_DEBUG  -fpermissive \
-Wparentheses -Wsequence-point -Wswitch-default \
-Wextra -Wundef -Wshadow -Wpointer-arith -Wbad-function-cast \
-Wc++-compat -Wwrite-strings -Wold-style-definition \
-Wmissing-prototypes -Wredundant-decls -Wnested-externs
# not used for now but interesting:
# -Wpacked
# -Wunreachable-code
# -ansi
# -std=c89
LDFLAGS=-lpthread -lutil -lboost_thread
CONTRIBDIR=../../../..
LWIPARCH=$(CONTRIBDIR)/ports/unix    
ARFLAGS=rs

#Set this to where you have the lwip core module checked out from CVS
#default assumes it's a dir named lwip at the same level as the contrib module
LWIPDIR=$(CONTRIBDIR)/../lwip/src


CFLAGS:=$(CFLAGS) \
-I. -I$(CONTRIBDIR)/apps/httpserver_raw -I$(CONTRIBDIR)/apps/shell \
-I$(CONTRIBDIR)/apps/tcpecho -I$(CONTRIBDIR)/apps/udpecho \
-I$(LWIPDIR)/include -I$(LWIPARCH)/include -I$(LWIPDIR)/include/ipv4 \
-I$(LWIPDIR) -I$(CONTRIBDIR)

# -I$(CLASSDIR)/inc

# COREFILES, CORE4FILES: The minimum set of files needed for lwIP.
COREFILES=$(LWIPDIR)/core/mem.c $(LWIPDIR)/core/memp.c $(LWIPDIR)/core/netif.c \
$(LWIPDIR)/core/pbuf.c $(LWIPDIR)/core/raw.c $(LWIPDIR)/core/stats.c \
$(LWIPDIR)/core/sys.c $(LWIPDIR)/core/tcp.c $(LWIPDIR)/core/tcp_in.c \
$(LWIPDIR)/core/tcp_out.c $(LWIPDIR)/core/udp.c $(LWIPDIR)/core/dhcp.c \
$(LWIPDIR)/core/init.c $(LWIPDIR)/core/timers.c $(LWIPDIR)/core/def.c \


CORE4FILES=$(wildcard $(LWIPDIR)/core/ipv4/*.c) $(LWIPDIR)/core/ipv4/inet.c \
$(LWIPDIR)/core/ipv4/inet_chksum.c

 # SNMPFILES: Extra SNMPv1 agent
SNMPFILES=$(LWIPDIR)/core/snmp/asn1_dec.c $(LWIPDIR)/core/snmp/asn1_enc.c \
$(LWIPDIR)/core/snmp/mib2.c $(LWIPDIR)/core/snmp/mib_structs.c \
$(LWIPDIR)/core/snmp/msg_in.c $(LWIPDIR)/core/snmp/msg_out.c

# APIFILES: The files which implement the sequential and socket APIs.
APIFILES=$(LWIPDIR)/api/api_lib.c $(LWIPDIR)/api/api_msg.c $(LWIPDIR)/api/tcpip.c \
$(LWIPDIR)/api/err.c $(LWIPDIR)/api/sockets.c $(LWIPDIR)/api/netbuf.c \    
$(LWIPDIR)/api/netdb.c

 # NETIFFILES: Files implementing various generic network interface functions.'
NETIFFILES=$(LWIPDIR)/netif/etharp.c $(LWIPDIR)/netif/slipif.c

# NETIFFILES: Add PPP netif
NETIFFILES+=$(LWIPDIR)/netif/ppp/auth.c $(LWIPDIR)/netif/ppp/chap.c \
$(LWIPDIR)/netif/ppp/chpms.c $(LWIPDIR)/netif/ppp/fsm.c \
$(LWIPDIR)/netif/ppp/ipcp.c $(LWIPDIR)/netif/ppp/lcp.c \
$(LWIPDIR)/netif/ppp/magic.c $(LWIPDIR)/netif/ppp/md5.c \
$(LWIPDIR)/netif/ppp/pap.c $(LWIPDIR)/netif/ppp/ppp.c \
$(LWIPDIR)/netif/ppp/randm.c $(LWIPDIR)/netif/ppp/vj.c \
$(LWIPARCH)/netif/sio.c

# ARCHFILES: Architecture specific files.
ARCHFILES=$(wildcard $(LWIPARCH)/*.c $(LWIPARCH)/netif/tapif.c $(LWIPARCH)/netif/tunif.c         
$(LWIPARCH)/netif/unixif.c $(LWIPARCH)/netif/list.c $(LWIPARCH)/netif/tcpdump.c)


# APPFILES: Applications.
APPFILES=$(CONTRIBDIR)/apps/httpserver_raw/fs.c     
$(CONTRIBDIR)/apps/httpserver_raw/httpd.c \
$(CONTRIBDIR)/apps/udpecho/udpecho.c $(CONTRIBDIR)/apps/tcpecho/tcpecho.c \
$(CONTRIBDIR)/apps/shell/shell.c 

# LWIPFILES: All the above.
LWIPFILES=$(COREFILES) $(CORE4FILES) $(SNMPFILES) $(APIFILES) $(NETIFFILES) $(ARCHFILES)
LWIPFILESW=$(wildcard $(LWIPFILES))
LWIPOBJS=$(notdir $(LWIPFILESW:.c=.o))
#LWIPOBJS+=$(notdir $(LWIPFILESW:.cpp=.o))

LWIPLIB=liblwip4.a
APPLIB=liblwipapps.a
APPOBJS=$(notdir $(APPFILES:.c=.o))
#APPOBJS+=$(notdir $(APPFILES:.cpp=.o))

%.o:
$(CC) $(CFLAGS) -c $(<:.o=.c)

all ipv4 compile: liblwip4.a 
#all ipv4 compile: simhost 
.PHONY: all

clean:
rm -f *.o $(LWIPLIB) $(APPLIB) simhost simnode simrouter *.s .depend* *.core core

depend dep: .depend

include .depend

$(APPLIB): $(APPOBJS)
$(AR) $(ARFLAGS) $(APPLIB) $?

$(LWIPLIB): $(LWIPOBJS)
$(AR) $(ARFLAGS) $(LWIPLIB) $?

 .depend: simhost.c simnode.c simrouter.c $(LWIPFILES) $(APPFILES)
 $(CCDEP) $(CFLAGS) -MM $^ > .depend || rm -f .depend

simhost: .depend $(LWIPLIB) $(APPLIB) simhost.o $(APPFILES)
$(CC) $(CFLAGS) $(LDFLAGS) -o simhost simhost.o $(APPLIB) $(LWIPLIB)

simrouter: .depend $(LWIPLIB) $(APPLIB) simrouter.o
$(CC) $(CFLAGS) $(LDFLAGS) -o simrouter simrouter.o $(APPLIB) $(LWIPLIB) 

simnode: .depend $(LWIPLIB) $(APPLIB) simnode.o 
$(CC) $(CFLAGS) $(LDFLAGS) -o simnode simnode.o $(APPLIB) $(LWIPLIB)

其中许多内容都不需要 - 这是'contrib'文件夹中的应用示例。所以...我得到了liblwip4.a库 - 现在一切都很好。

使用这个库我做了一些测试应用程序 - 一个使用lwip lib进行不同连接的类。我使用了eclipse IDE(添加了所有包含,liblwip4.a等等),它运行正常。

现在我想用这个lwip lib和我的类创建一个my_lwiplib.a或my_lwiplib.so。我创建了3个文件夹的目录--lwip(sourse文件),contrib-1.4.1(平台相关文件等)和lwipClass(我的.h和.cpp文件)。写了makefile:

CC = g++

CFLAGS = -fPIC -g -fpermissive
LDFLAGS = -shared
READYLIB = ./contrib-1.4.1/ports/unix/proj/unixsim/liblwip4.a

SOURCES  =  $(wildcard lwipClass/src/*.cpp)
INCLUDES = -I./lwipClass/inc/ -I./lwip/src/include/ -I./lwip/src/include/lwip/
OBJECTS  = $(SOURCES:.cpp=.o)

CFLAGS += $(INCLUDES)

TARGET_SO        =    libmy_lwip.so
TARGET_STATIC    =    libmy_lwip.a


clean:
    rm -f $(OBJECTS) $(TARGET_SO) $(TARGET_STATIC) 

shared : $(OBJECTS)
    $(CC) $(CFLAGS) $(OBJECTS) $(READYLIB) -o $(TARGET_SO) $(LDFLAGS)   

static : $(OBJECTS)    
    ar rcs $(TARGET_STATIC) $(OBJECTS) $(READYLIB)

当我'共享'时,我得到:

sudo make shared
g++ -fPIC -g -fpermissive -I./lwipClass/inc/ -I./lwip/src/include/ -    
I./lwip/src/include/lwip/ lwipClass/src/lwipClass.o ./contrib-    
1.4.1/ports/unix/proj/unixsim/liblwip4.a -o libmy_lwip.so -shared   
/usr/bin/ld: lwipClass/src/lwipClass.o: relocation R_X86_64_32 against `.bss' can not be     
used when making a shared object; recompile with -fPIC
lwipClass/src/lwipClass.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
make: *** [shared] Error 1

这里有什么问题?

增加14.08

尝试编译静态库。它编译好了。 将它链接到eclipse测试项目并进行测试应用。

  classA *myClass;
  myClass->getInstance();

当我尝试编译时,我得到了

make all 
Building file: ../src/test.cpp
Invoking: GCC C++ Compiler
g++ -fpermissive -I/home/user/lwip/lwipClass/inc -O0 -g3 -Wall -c -fmessage-length=0 -   
MMD -MP -MF"src/test.d" -MT"src/test.d" -o "src/test.o" "../src/test.cpp"
Finished building: ../src/test.cpp

Building target: test
Invoking: GCC C++ Linker
g++  -o "test"  ./src/test.o  /home/user/lwip/libmy_lwip.a -lpthread -lboost_thread
/home/user/lwip/libmy_lwip.a(lwipClass.o): In function     
`lwipImpl::tcpecho_thread(void*)':
lwipClass.cpp:(.text+0x85): undefined reference to `netbuf_data'
lwipClass.cpp:(.text+0xb9): undefined reference to `netbuf_next'
lwipClass.cpp:(.text+0xce): undefined reference to `netbuf_delete'
lwipClass.cpp:(.text+0xef): undefined reference to `netconn_recv'

这意味着没有这样的功能。

我做

 user:~/lwip$ objdump -t (some way /)/liblwip4.a |grep netbuf_data
 00000000000003df g     F .text 0000000000000103 netbuf_data

比我做

usr:~/lwip$ objdump -t (some way/)lwip/libmy_lwip.a |grep netbuf_data
0000000000000000         *UND*  0000000000000000 netbuf_data
objdump: liblwip4.a: File format not recognized

WTF ?????

1 个答案:

答案 0 :(得分:2)

为了构建共享库,您必须首先编译源代码并生成position-independent目标文件。这是-fPIC标志的用途。你不能从&#34;普通&#34;中建立共享库。对象文件,您以后不能更改对象文件的属性 - 至少不容易。

在您的示例中,您尝试通过静态库()从位置相关的目标文件构造共享库。您可以从这些对象构造静态库,但是如果您想构建共享库,正如链接器告诉您的那样,您必须 {{1} }