为什么在构建共享库时添加一个空main函数的.cpp文件后,undefined reference消失了
Why does undefined reference disappear after adding a .cpp file with empty main function when building shared library
我有构建共享库的 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)
但是当我尝试编译它时,我得到 undefined reference to ...
的错误。好吧,虽然我不明白为什么会存在这些错误,但我发现 将带有空 main
函数的 .cpp
文件添加到包含其他 .cpp
文件的目录中可以修复所有问题东西:
//empty.cpp
int main()
{
return 0;
}
在重建共享库后,我成功地创建并执行了 xor
。
问题是:这是怎么回事?
我怀疑添加额外的文件是否真的解决了任何问题。很可能是其他一些副作用有所帮助。
您的问题是您的 link 行不正确。与大多数 UNIX linker 一样,GCC 是 single-passlinker。这意味着它只遍历所有库一次以查找未解析的符号。 that 意味着 linker 的参数顺序非常重要:你必须确保如果项目 A 引用项目 B 中的符号,那么 A 会出现 之前B在link行。
在您的示例中,您将所有库放在前面,将源文件放在最后。因此,当 make 开始查看您的库时,它还没有看到您的源代码,并且没有它需要 link 的符号。当它编译您的源代码时,没有剩余的库可以从中解析符号。
您的 link 行应首先排列源文件和目标文件,然后是库(按引用 ... 引用顺序):
$(CC) $(FLAGS) $(SOURCE) -L$(LIB_DIR) $(SIMPLETRON) $(ALGEBRA) $(PUGI) -o $(XOR)
我有构建共享库的 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)
但是当我尝试编译它时,我得到 undefined reference to ...
的错误。好吧,虽然我不明白为什么会存在这些错误,但我发现 将带有空 main
函数的 .cpp
文件添加到包含其他 .cpp
文件的目录中可以修复所有问题东西:
//empty.cpp
int main()
{
return 0;
}
在重建共享库后,我成功地创建并执行了 xor
。
问题是:这是怎么回事?
我怀疑添加额外的文件是否真的解决了任何问题。很可能是其他一些副作用有所帮助。
您的问题是您的 link 行不正确。与大多数 UNIX linker 一样,GCC 是 single-passlinker。这意味着它只遍历所有库一次以查找未解析的符号。 that 意味着 linker 的参数顺序非常重要:你必须确保如果项目 A 引用项目 B 中的符号,那么 A 会出现 之前B在link行。
在您的示例中,您将所有库放在前面,将源文件放在最后。因此,当 make 开始查看您的库时,它还没有看到您的源代码,并且没有它需要 link 的符号。当它编译您的源代码时,没有剩余的库可以从中解析符号。
您的 link 行应首先排列源文件和目标文件,然后是库(按引用 ... 引用顺序):
$(CC) $(FLAGS) $(SOURCE) -L$(LIB_DIR) $(SIMPLETRON) $(ALGEBRA) $(PUGI) -o $(XOR)