为什么在构建共享库时添加具有空 main 函数的 .cpp 文件后未定义的引用消失

Why does undefined reference disappear after adding a .cpp file with empty main function when building shared library

提问人:LRDPRDX 提问时间:11/24/2018 更新时间:11/24/2018 访问量:113

问:

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

#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)

但是当我尝试编译它时,我得到错误。好的,虽然我不明白为什么存在这些错误,但我发现将具有空函数的 .cpp 文件添加到包含其他 .cpp 文件的目录中可以修复所有问题undefined reference to ...

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

在重建共享库后,我成功制作并执行。 问题是:这是怎么回事?xor

Makefile G++ 未定义引用

评论


答:

1赞 MadScientist 11/24/2018 #1

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

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

在您的示例中,您将所有库放在首位,将源文件放在最后。因此,当 make 开始查看您的库时,它还没有看到您的源代码,并且不需要链接任何符号。当它编译您的源代码时,已经没有库可以解析符号了。

您的链接行应该首先使用源文件和目标文件进行排列,然后是库(在 referencer ...参考顺序):

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