2017-02-20 32 views
3

Я готовлю C++-приложение на Linux (Ubuntu 16.04) с помощью нескольких библиотек poco, с которыми я динамически связан. У меня есть папка проекта, которая состоит из: include, bin, lib, src и build folders и соответствующего Makefile. До сих пор я использовал следующий Makefile, который получил библиотеки из/USR/местные/Библиотека

CC := g++ 

# Folders 
SRCDIR := src 
BUILDDIR := build 
TARGETDIR := bin 

# Targets 
EXECUTABLE := C++_APP 
TARGET := $(TARGETDIR)/$(EXECUTABLE) 

SRCEXT := cpp 
SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) 
CFLAGS := -c -Wall 
INC := -I include -I /usr/local/include 
LIB := -L /usr/local/lib -lPocoFoundation -lPocoNet -lPocoUtil 

$(TARGET): $(OBJECTS) 
@echo " Linking..." 
@echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -o $(TARGET) $(LIB) 

$(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) 
@mkdir -p $(BUILDDIR) 
@echo " $(CC) $(CFLAGS) $(INC) -c -o [email protected] $<"; $(CC) $(CFLAGS) $(INC) -c -o [email protected]  $< 

clean: 
@echo " Cleaning..."; 
@echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET) 

.PHONY: clean 

Теперь я хотел бы во время запуска компоновщика для поиска библиотек только в проекте Lib папки без изменения LD_LIBRARY_PATH или редактирования ЛД. so.conf. Поэтому я искал, и я обнаружил, что это может быть достигнуто с помощью аргумента компоновщика -Wl, rpath, $ ORIGIN. Поэтому я полагаю, что мне нужно добавить следующее заявление

LDFLAGS := -Wl,-rpath,$ORIGIN/../lib 

и изменить заявление LIB следующим образом:

LIB := -L $ORIGIN/../lib -lPocoFoundation -lPocoNet -lPocoUtil 

Однако до сих пор получить библиотеки из каталога по умолчанию (USR/местные/Lib), так как я тестировал его без библиотеки в папке проекта lib. Что я сделал не так?

+0

'LIB: = -L $ (ORIGIN) /../ lib -lPocoFoundation -lPocoNet -lPocoUtil'? Обратите внимание:() – skomp

+0

@skomp Тот же результат с $ (ORIGIN). Он извлекает библиотеки из папки по умолчанию, а не в проектную. – dk13

+0

Параметр -rpath linker не заменяет путь поиска библиотеки по умолчанию, но добавляет к нему еще одну запись. So -rpath работает в ситуациях, когда lib не находится в пути поиска по умолчанию. Не ваше дело, не так ли?Попробуйте передать вам полные пути к libs в командной строке линкера. Что-то вроде '-l $ ORIGIN /../ lib/PocoFoundation' –

ответ

5

Нет, вы недоразумение. Вы должны передать литеральную строку $ORIGIN/../lib в качестве аргумента для вашего компоновщика. Токен $ORIGIN хранится внутри вашей программы после ее создания, и когда компоновщик времени выполнения запускает вашу программу, он заменит $ORIGIN на текущий путь, из которого была вызвана ваша программа. Это верно, даже если вы скопировали свою программу в другом месте. Поэтому, если вы запустите свою программу как /usr/local/bin/myprogram, тогда компоновщик времени выполнения заменит $ORIGIN на /usr/local/bin. Если вы скопируете его на /opt/mystuff/libexec/myprogram, тогда компоновщик времени выполнения заменит $ORIGIN на /opt/mystuff/libexec.

Чтобы передать буквальный $ к команде, вызываемой рецепт макияжа, вы должны избежать $ путем удвоения его: $$. В противном случае make увидит $ как введение переменной или функции make. Помните, что это совершенно законно для переменных делают, чтобы избежать круглых скобок и т.д., если это один символ (примечания, [email protected], $< и т.д.)

Так что, когда вы пишете -Wl,-rpath,$ORIGIN/../lib делает будут интерпретировать $O в $ORIGIN, как расширяя переменную с именем O, которая пуста, давая вам -Wl,-rpath,RIGIN/../lib.

Также вы должны избежать $ из оболочки, в противном случае он попытается развернуть $ORIGIN в качестве переменной оболочки, которую вы не хотите.

Вы хотите сделать что-то вроде этого:

LDFLAGS = '-Wl,-rpath,$$ORIGIN/../lib' -L/usr/local/lib 
LDLIBS = -lPocoFoundation -lPocoNet -lPocoUtil 

$(TARGET): $(OBJECTS) 
     @echo " Linking..." 
     $(CC) $^ -o [email protected] $(LDFLAGS) $(LDLIBS) 

(я не знаю, почему вы используете @ скрыть команду, а затем повторить команду ... почему бы не просто вынуть @ и тому echo и позвольте сделать вам команду?)

+0

Спасибо за ваш ответ. Только одно уточнение, которое я пробовал, не имеет библиотеки в папке проекта lib, которая находится внутри/home/user/project/lib, и компоновщик все еще их нашел. Я также опустил -L/usr/local/lib, то же самое. Я также заменил -L $$ ORIGIN /../ lib, но не повезло. Возможно ли для компоновщика проверить только папку/home/user/project/lib для необходимых библиотек? – dk13

+0

Параметр '-rpath' контролирует поиск разделяемых библиотек в RUNTIME; то есть при вызове вашей программы. Это не имеет никакого отношения к поиску библиотек в LINK TIME. Это контролируется опцией '-L'. Это две совершенно разные вещи без перекрытия; компоновщик не будет смотреть на настройки '-rpath', а загрузчик времени выполнения не будет смотреть на каталоги, предоставленные' -L'. Поэтому, если вы пытаетесь понять поведение во время выполнения, вы должны просто полностью игнорировать флаг '-L': это не имеет значения. – MadScientist

+0

У загрузчика времени выполнения есть алгоритм, используемый для поиска разделяемых библиотек. Вы можете прочитать об этом алгоритме через 'man ld.so' (' ld.so' - код загрузчика во время выполнения). Он всегда будет искать библиотеки, использующие сначала 'DT_RPATH' (это то, что задается опцией' -rpath'). Однако, если библиотека там не найдена, она продолжит поиск в других местах. Скорее всего, ваша система настроена на поиск библиотек в '/ usr/local/lib' и т. Д. Я не знаю, как заставить загрузчика времени перестать искать места по умолчанию и сбой, если библиотека не найдена в 'DT_RPATH' – MadScientist