我正在linux(Ubuntu 16.04)上准备一个c ++应用程序,使用了一些动态链接的poco库。我有项目文件夹,包括:include,bin,lib,src和build文件夹以及相关的Makefile。到目前为止,我使用了以下Makefile,它从/ usr / local / lib
获取了库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 $@ $<"; $(CC) $(CFLAGS) $(INC) -c -o $@ $<
clean:
@echo " Cleaning...";
@echo " $(RM) -r $(BUILDDIR) $(TARGET)"; $(RM) -r $(BUILDDIR) $(TARGET)
.PHONY: clean
现在我想在运行链接器时只在项目lib文件夹中搜索库而不更改LD_LIBRARY_PATH或编辑ld.so.conf。所以我搜索了一下,发现这可以通过链接器参数-Wl,rpath,$ ORIGIN来实现。所以我假设我需要添加以下语句
LDFLAGS := -Wl,-rpath,$ORIGIN/../lib
并更改LIB语句如下:
LIB := -L $ORIGIN/../lib -lPocoFoundation -lPocoNet -lPocoUtil
然而,它仍然从默认目录(usr / local / lib)获取库,因为我在项目lib文件夹中没有库测试它。我做错了什么?
答案 0 :(得分:13)
不,你有误会。您需要将文字字符串$ORIGIN/../lib
作为参数传递给链接器。 $ORIGIN
令牌在创建后保存在程序中,当运行时链接程序开始运行程序时,它将用调用程序的当前路径替换$ORIGIN
。即使您已将程序复制到其他位置,也是如此。因此,如果您将程序作为/usr/local/bin/myprogram
运行,则运行时链接程序将$ORIGIN
替换为/usr/local/bin
。如果将其复制到/opt/mystuff/libexec/myprogram
,则运行时链接程序将$ORIGIN
替换为/opt/mystuff/libexec
。
为了将文字$
传递给make配方调用的命令,你必须通过加倍$
来逃避$$
:$
。否则,make会将$@
视为引入make变量或函数。请记住,make变量避免使用括号等是完全合法的,如果它是单个字符(注意,$<
,-Wl,-rpath,$ORIGIN/../lib
,等)
因此,当您撰写$O
时,make会将$ORIGIN
中的O
解释为扩展名为-Wl,-rpath,RIGIN/../lib
的变量,该变量为空,为您提供$
。
此外,您必须从shell中转义$ORIGIN
,否则它会尝试将LDFLAGS = '-Wl,-rpath,$$ORIGIN/../lib' -L/usr/local/lib
LDLIBS = -lPocoFoundation -lPocoNet -lPocoUtil
$(TARGET): $(OBJECTS)
@echo " Linking..."
$(CC) $^ -o $@ $(LDFLAGS) $(LDLIBS)
扩展为您不想要的shell变量。
你想做这样的事情:
@
(我不知道为什么你使用@
隐藏命令,然后回应命令...为什么不只是取出echo
和internal
和让make告诉你命令?)