如何在 Makefile 中正确包含 -Wl,-rpath,$ORIGIN 链接器参数?
我正在使用一些我动态链接的 poco 库在 linux (Ubuntu 16.04) 上准备一个 c++ 应用程序.我的项目文件夹包括:include、bin、lib、src 和 build 文件夹以及相关的 Makefile.到目前为止,我使用了以下 Makefile 从/usr/local/lib 获取库
I'm preparing a c++ app on linux (Ubuntu 16.04) with the use of a few poco libraries which I have dynamically linked. I have project folder that consists of : include, bin, lib , src and build folders and the relevant Makefile. So far I used the following Makefile which got the libraries from /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来实现.所以我假设我需要添加以下语句
Now I'd like during running the linker to search for libraries only in project lib folder without changing LD_LIBRARY_PATH or editing ld.so.conf. So I searched and I found that this can be achieved by the linker argument -Wl,rpath,$ORIGIN. So I assume that I need to add the following statement
LDFLAGS := -Wl,-rpath,$ORIGIN/../lib
并将 LIB 语句更改如下:
and change the the LIB statement as following:
LIB := -L $ORIGIN/../lib -lPocoFoundation -lPocoNet -lPocoUtil
但是它仍然从默认目录 (usr/local/lib) 获取库,因为我在项目 lib 文件夹中没有库的情况下对其进行了测试.我做错了什么?
However it still get the libraries from the default directory (usr/local/lib) , since I tested it with no library on the project lib folder. What have I done wrong?
推荐答案
不,你误会了.您需要将文字字符串 $ORIGIN/../lib
作为参数传递给链接器.$ORIGIN
标记在创建后保存在您的程序中,当运行时链接器开始运行您的程序时,它会将 $ORIGIN
替换为您的程序被调用的当前路径从.即使您将程序复制到其他地方也是如此.因此,如果您将程序作为 /usr/local/bin/myprogram
运行,则运行时链接器会将 $ORIGIN
替换为 /usr/local/bin
.如果将其复制到 /opt/mystuff/libexec/myprogram
,则运行时链接器会将 $ORIGIN
替换为 /opt/mystuff/libexec
.
No, you're misunderstanding. You need to pass the literal string $ORIGIN/../lib
as an argument to your linker. The $ORIGIN
token is kept inside your program after it's created and when the runtime linker starts to run your program it will replace $ORIGIN
with the current path that your program was invoked from. This is true even if you've copied your program somewhere else. So if you run your program as /usr/local/bin/myprogram
then the runtime linker will replace $ORIGIN
with /usr/local/bin
. If you copy it to /opt/mystuff/libexec/myprogram
then the runtime linker will replace $ORIGIN
with /opt/mystuff/libexec
.
为了将文字 $
传递给 make 配方调用的命令,您必须通过加倍来转义 $
:$$代码>.否则,make 会将
$
视为引入了 make 变量或函数.请记住,make 变量避免括号等是完全合法的,if 它是单个字符(注意,$@
、$<
等)
In order to pass a literal $
to the command invoked by a make recipe, you have to escape the $
by doubling it: $$
. Otherwise, make will see the $
as introducing a make variable or function. Remember, it's perfectly legal for a make variable to avoid the parentheses etc., if it's a single character (note, $@
, $<
, etc.)
所以当你编写 -Wl,-rpath,$ORIGIN/../lib
时,make 会解释 $ORIGIN
中的 $O
作为扩展名为 O
的变量,它是空的,给你 -Wl,-rpath,RIGIN/../lib
.
So when you write -Wl,-rpath,$ORIGIN/../lib
make will interpret the $O
in $ORIGIN
as expanding a variable named O
, which is empty, giving you -Wl,-rpath,RIGIN/../lib
.
您还必须将 $
从 shell 中转义,否则它将尝试将 $ORIGIN
扩展为您不想要的 shell 变量.
Also you have to escape the $
from the shell, otherwise it will try to expand $ORIGIN
as a shell variable which you don't want.
你想做这样的事情:
LDFLAGS = '-Wl,-rpath,$$ORIGIN/../lib' -L/usr/local/lib
LDLIBS = -lPocoFoundation -lPocoNet -lPocoUtil
$(TARGET): $(OBJECTS)
@echo " Linking..."
$(CC) $^ -o $@ $(LDFLAGS) $(LDLIBS)
(不知道你为什么用@
隐藏命令,然后回显命令...为什么不直接取出@
和echo
然后让 make 给你看命令?)
(I don't know why you use @
to hide the command, then echo the command... why not just take out the @
and the echo
and let make show you the command?)
相关文章