将环境变量从Makefile导出到Shell

时间:2019-12-11 21:33:25

标签: makefile gnu-make

我想修改并导出“ LD_LIBRARY_PATH”环境变量,以便将libjvm.so与我的代码链接。以下是我的Makefile:

<img id="mainImage" src="https://source.unsplash.com/random/201x200" alt="" width="200" />

<div id="galleryImages">
   <img class="galleryHover" src="https://source.unsplash.com/random/201x200"/>
   <img class="galleryHover" src="https://source.unsplash.com/random/200x201"/>
</div>

在名为“ run”的目标中,我导出“ LD_LIBRARY_PATH”环境变量。但是它不会导出到我当前的shell中。

我收到以下错误: ./hello_world_c_exec:加载共享库时出错:libjvm.so:无法打开共享库文件:没有这样的文件或目录

如何使用Makefile导出'LD_LIBRARY_PATH'?

1 个答案:

答案 0 :(得分:1)

配方的每一行通常都在单独的shell中执行,这意味着您的export行与./hello_world_c_exec行进入不同的shell。亲自看看:

$ cat Makefile
JVM_DIR := /tools/opt/jdk-10.0.2/lib/server

foo: LDLIBS := -ljvm
foo: LDFLAGS := -L$(JVM_DIR)

.PHONY: run
run: foo
        export LD_LIBRARY_PATH=$(JVM_DIR)
        $(<D)/$(<F)

输出:

$ make run -d
...
Must remake target 'run'.
export LD_LIBRARY_PATH=/tools/opt/jdk-10.0.2/lib/server
Putting child 0x81ee20 (run) PID 18709 on the chain.
Live child 0x81ee20 (run) PID 18709
Reaping winning child 0x81ee20 PID 18709
./foo
Live child 0x81ee20 (run) PID 18710
./foo: error while loading shared libraries: libjvm.so: cannot open shared object file: No such file or directory
Reaping losing child 0x81ee20 PID 18710
make: *** [Makefile:9: run] Error 127

请注意,对于每个单独的行,开始了两个单独的过程(18709和18710)。如果它可以通过以下几种方法在单个shell中运行,则可以使其工作:

  1. 将其制作为单个脚本:
$ cat Makefile
JVM_DIR := /tools/opt/jdk-10.0.2/lib/server

foo: LDLIBS := -ljvm
foo: LDFLAGS := -L$(JVM_DIR)

.PHONY: run
run: foo
        export LD_LIBRARY_PATH=$(JVM_DIR); \
        $(<D)/$(<F)

$ make run -d
...
Must remake target 'run'.
export LD_LIBRARY_PATH=/tools/opt/jdk-10.0.2/lib/server; \
./foo
Putting child 0x21aa780 (run) PID 22009 on the chain.
Live child 0x21aa780 (run) PID 22009
Reaping winning child 0x21aa780 PID 22009
Removing child 0x21aa780 PID 22009 from chain.
Successfully remade target file 'run'.
  1. 直接在命令行中设置:
$ cat Makefile
JVM_DIR := /tools/opt/jdk-10.0.2/lib/server

foo: LDLIBS := -ljvm
foo: LDFLAGS := -L$(JVM_DIR)

.PHONY: run
run: foo
        LD_LIBRARY_PATH=$(JVM_DIR) $(<D)/$(<F)

$ make run
LD_LIBRARY_PATH=/tools/opt/jdk-10.0.2/lib/server ./foo
  1. 打开One Shell,以便在单个shell中执行配方,而不是为每一行分别在单独的shell中执行:
$ cat Makefile
JVM_DIR := /tools/opt/jdk-10.0.2/lib/server

foo: LDLIBS := -ljvm
foo: LDFLAGS := -L$(JVM_DIR)

.ONESHELL:

.PHONY: run
run: foo
        export LD_LIBRARY_PATH=$(JVM_DIR)
        $(<D)/$(<F)

$ make run -d
...
Must remake target 'run'.
export LD_LIBRARY_PATH=/tools/opt/jdk-10.0.2/lib/server
./foo
Putting child 0x25258f0 (run) PID 31367 on the chain.
Live child 0x25258f0 (run) PID 31367
Reaping winning child 0x25258f0 PID 31367
Removing child 0x25258f0 PID 31367 from chain.
Successfully remade target file 'run'.

我个人会选择其他方法。

首先,设置LD_LIBRARY_PATH很麻烦,并且取决于各种设置,可能会导致其他事情失败,例如,当系统已经将LD_LIBRARY_PATH设置为其他东西时;至少您应该附加到变量,而不是将其设置为严格的值。

第二,这仍然留下了在Makefile之外运行可执行文件的问题。即使构建了二进制文件,通过简单的调用来运行它也不是那么简单:

$ make run
cc   -L/tools/opt/jdk-10.0.2/lib/server  foo.c  -ljvm -o foo
export LD_LIBRARY_PATH=/tools/opt/jdk-10.0.2/lib/server
./foo
$ ./foo
./foo: error while loading shared libraries: libjvm.so: cannot open shared object file: No such file or directory

相反,我会告诉链接程序将提示嵌入在哪里可以找到库,从而根本不需要LD_LIBRARY_PATH

$ cat Makefile
JVM_DIR := /tools/opt/jdk-10.0.2/lib/server

foo: LDLIBS := -ljvm
foo: LDFLAGS := -L$(JVM_DIR) -Wl,-rpath,$(JVM_DIR)

.PHONY: run
run: foo
        $(<D)/$(<F)

$ make run
cc   -L/tools/opt/jdk-10.0.2/lib/server -Wl,-rpath,/tools/opt/jdk-10.0.2/lib/server  foo.c  -ljvm -o foo
./foo

$ ./foo
$ echo $?
0