Почему неопределенная ссылка исчезает после добавления файла .cpp с пустой основной функцией при создании разделяемой библиотеки - PullRequest
0 голосов
/ 24 ноября 2018

У меня есть make-файл, который собирает общую библиотеку 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 ....Хорошо, хотя я не понимаю, почему существуют эти ошибки, я обнаружил, что добавление файла .cpp с пустой функцией main в каталог с другими файлами .cpp исправляет все вещи :

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

И после перестроения разделяемой библиотеки я успешно создаю и выполняю xor.Вопрос в том, что здесь происходит?

1 Ответ

0 голосов
/ 24 ноября 2018

Я сомневаюсь, что добавление дополнительного файла действительно исправило что-либо.Скорее всего, помог какой-то другой побочный эффект.

Ваша проблема в том, что ваша строка ссылки неверна.GCC, как и большинство линкеров UNIX, является однопроходным линкером.Это означает, что он только обходит все библиотеки один раз в поисках неразрешенных символов.И , что означает, что порядок аргументов для компоновщика является критически важным: вы должны убедиться, что если элемент A ссылается на символы в элементе B, то A предшествует перед B по ссылкеline.

В вашем примере вы помещаете все свои библиотеки в первую , а ваши исходные файлы в последнюю очередь .Итак, когда make начинает просматривать ваши библиотеки, он еще не видел ваши источники, и нет никаких символов, на которые нужно ссылаться.К тому времени, когда он компилирует ваши исходники, не осталось библиотек для разрешения символов из.

В вашей строке ссылки должны быть сначала источники и объектные файлы, а затем библиотеки (в порядке ссылки ... в порядке ссылок):

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