Every line of a recipe is normally executed in a separate shell, meaning that your export
line gets into different shell than your ./hello_world_c_exec
line. See for yourself:
$ 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)
Output:
$ 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
Note two separate processes started (18709 and 18710) for each separate line. You can make it work if it's run in a single shell with a couple of ways:
- Make it a single script:
$ 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'.
- Set in on the command line directly:
$ 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
- Turn on One Shell so that recipe is executed in a single shell instead of separate shell for each line:
$ 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'.
Personally, I would choose yet different approach.
First, setting up LD_LIBRARY_PATH
is cumbersome and depending on various settings may cause other things to fail, for example when your system already sets LD_LIBRARY_PATH
to something else; at the very least you should be appending to the variable not setting it to a strict value.
Second, this still leaves the problem of running the executable outside of your Makefile
. Even when the binary was built, it is not that trivial to run it by just a simple invocation:
$ 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
Instead, I would tell the linker to embed the hint where to find the library, so that the LD_LIBRARY_PATH
is not needed at all:
$ 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
export LD_LIBRARY_PATH=...; ./hello_world_c_exec
. If that works, I'll explain why. – BetaLD_LIBRARY_PATH=... ./hello_world_c_exec
. – MadScientist