为什么在构建共享库时,添加一个主函数为空的.cpp文件后,未定义的引用会消失



我有构建共享库libsimpletron.so:的makefile

#shell
MKDIR_P = mkdir -p
#compiler
CC = g++
#cpp flags
FLAGS      = -std=c++1z
CPPFLAGS   = -fPIC -Wall -Wextra 
LDFLAGS    = -shared
#directories
INC_DIR = ../inc
LIB_DIR = ../lib
BIN_DIR = ../bin
OBJ_DIR = ./obj
ALG_DIR = ./algebra 

SOURCES = $(shell echo *.cpp)
HEADERS = $(shell echo $(INC_DIR)/*.h)
_OBJECTS = $(SOURCES:.cpp=.o)
OBJECTS = $(patsubst %,$(OBJ_DIR)/%,$(_OBJECTS))
ALGEBRA = $(LIB_DIR)/libalgebra.so
TARGET = $(LIB_DIR)/libsimpletron.so
.PHONY: directories
all : directories $(ALGEBRA) $(TARGET)

directories: $(OBJ_DIR) $(BIN_DIR) $(LIB_DIR)
$(OBJ_DIR):
$(MKDIR_P) $(OBJ_DIR)
$(BIN_DIR):
$(MKDIR_P) $(BIN_DIR)
$(LIB_DIR):
$(MKDIR_P) $(LIB_DIR)
$(ALGEBRA):
$(MAKE) -C $(ALG_DIR)

$(OBJ_DIR)/%.o: %.cpp $(HEADERS)
$(CC) -c $(FLAGS) $(CPPFLAGS) -o $@ $<
$(TARGET) : $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $^

.PHONY: clean
clean:
rm -f $(OBJ_DIR)/*.o

make命令成功构建库(我认为(:

g++ -c -std=c++1z -fPIC -Wall -Wextra  -o obj/builder.o builder.cpp
...similar lines for each .cpp file...
g++ -shared -o ../lib/libsimpletron.so obj/builder.o obj/gradient_trainer.o obj/layer.o obj/neuron.o obj/perceptron.o obj/simpletron.o obj/trainer.o

然后我试着使用这个图书馆。我将测试xor编译如下:

#compiler
CC = g++
#cpp flags
FLAGS       = -std=c++1z
PUGI        = -l pugixml
#directories
LIB_DIR = /home/lrdprdx/Projects/SimplePerceptron/lib
SIMPLETRON  = -lsimpletron
ALGEBRA     = -lalgebra
XOR     = xor
SOURCE  = xor.cpp
#config file
CONFIG  = config.xml

$(XOR) : $(SOURCE) $(CONFIG)
$(CC) $(FLAGS) -L$(LIB_DIR) $(SIMPLETRON) $(ALGEBRA) $(PUGI) -o $(XOR) $(SOURCE)

但当我试图编译这个时,我会得到undefined reference to ...的错误。好吧,虽然我不明白为什么会存在这些错误,但我发现将一个带有空main函数的.cpp文件添加到带有其他.cpp文件的目录中可以修复所有东西

//empty.cpp
int main()
{
return 0;
}

重建共享库后,成功地制作并执行了xor。问题是:这里发生了什么?

我怀疑添加额外的文件是否真的解决了任何问题。很可能还有其他副作用。

你的问题是你的链接线不正确。GCC与大多数UNIX链接器一样,是一个单程链接器。这意味着它只遍历所有库一次,查找未解析的符号。意味着链接器参数的顺序至关重要:您必须确保,如果项目A引用项目B中的符号,则A在链接行上位于B之前。

在您的示例中,您将所有库放在第一个,而源文件则放在最后。所以,当make开始查看你的库时,它还没有看到你的源代码,也没有需要链接的符号。当它编译您的源代码时,已经没有库可以从中解析符号了。

你的链接行应该首先安排源和对象文件,然后是库(按照引用…引用的顺序(:

$(CC) $(FLAGS) $(SOURCE) -L$(LIB_DIR) $(SIMPLETRON) $(ALGEBRA) $(PUGI) -o $(XOR)

最新更新