makefile - 将环境变量从 makefile 导出到 shell
问题描述
我想修改和导出“LD_LIBRARY_PATH”环境变量,以便将 libjvm.so 与我的代码链接起来。下面是我的Makefile:
all: run
helloWorld.class: helloWorld.java
javac helloWorld.java
hello_world: hello_world.c
gcc -L/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/ -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux/ hello_world.c -o hello_world_c_exec -ljvm
run: helloWorld.class hello_world
export LD_LIBRARY_PATH="/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server/"
./hello_world_c_exec
clean:
rm -f helloWorld.class hello_world
在名为“run”的目标中,我导出“LD_LIBRARY_PATH”环境变量。但它不会导出到我当前的外壳。
我收到以下错误:./hello_world_c_exec:加载共享库时出错:libjvm.so:无法打开共享对象文件:没有这样的文件或目录
如何使用 makefile 导出“LD_LIBRARY_PATH”?
解决方案
配方的每一行通常在单独的 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 中运行,您可以通过以下几种方式使其工作:
- 使其成为单个脚本:
$ 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'.
- 直接在命令行中设置:
$ 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
- 打开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
推荐阅读
- tinymce - TinyMCE复制粘贴IE11
- javascript - 在现代 Firefox/Chrome/Edge 浏览器中对 PDF 进行数字签名
- sharepoint - 如何自动将视频添加到一页?
- javascript - 如何使用html中的箭头在不同部分显示下拉菜单
- docker - 如何在 YAML 中使用变量作为键?\
- python-3.x - 用 word2vec 用相似度替换随机词
- spring - 我们可以在同一个端口上运行多个 Spring Boot 应用程序吗?如果没有,为什么我们在 application.properties 中有上下文路径选项?
- winforms - 如何使用 .Net 平台中的服务自动在线执行任务?
- mysql - MySQL 在表连接中不使用索引
- azure-logic-apps - Azure 逻辑应用设计器中对资源组筛选 Azure API 连接的限制何时解除?