halcyon / asdf-java

A Java plugin for asdf-vm.
MIT License
466 stars 86 forks source link

Plugin should export JAVA_HOME at bin/exec-env #154

Open vic opened 3 years ago

vic commented 3 years ago

Environment variables should be exported at bin/exec-env instead of requiring the user to source another script in their shellrc.

See https://asdf-vm.com/#/plugins-create?id=binexec-env

howardburgess commented 3 years ago

If I'm not mistaken, the scripts e.g. . ~/.asdf/plugins/java/set-java-home.fish (docs) are for exporting the $JAVA_HOME for other programs that need it, rather than for the commands made available by this plugin (java, javac etc). The bin/exec-env is only sourced just before actually running a command.

Some experiments (I use the fish shell):

Create a script ~/.asdf/plugins/java/bin/exec-env:

echo "exec-env: \$0 is $0" >&2
echo "exec-env: args are $*" >&2
test -n "$BASH" && echo "exec-env: Running in bash" >&2
env | grep ASDF >&2
export myvar=myvalue

Clear the prompt, in case anything is calling Java/asdf commands from it.

$ function fish_prompt
      echo '$ '
  end

Running java -version shows that exec-env is sourced before and after the command.

$ java -version
exec-env: $0 is /Users/howard/.asdf/bin/asdf
exec-env: args are java zulu-11.48.21 run_within_env
exec-env: Running in bash
ASDF_INSTALL_VERSION=zulu-11.48.21
ASDF_INSTALL_TYPE=version
ASDF_INSTALL_PATH=/Users/howard/.asdf/installs/java/zulu-11.48.21
ASDF_DIR=/Users/howard/.asdf
openjdk version "11.0.11" 2021-04-20 LTS
OpenJDK Runtime Environment Zulu11.48+21-CA (build 11.0.11+9-LTS)
OpenJDK 64-Bit Server VM Zulu11.48+21-CA (build 11.0.11+9-LTS, mixed mode)
exec-env: $0 is /Users/howard/.asdf/bin/asdf
exec-env: args are java zulu-11.48.21 run_within_env
exec-env: Running in bash
ASDF_INSTALL_VERSION=zulu-11.48.21
ASDF_INSTALL_TYPE=version
ASDF_INSTALL_PATH=/Users/howard/.asdf/installs/java/zulu-11.48.21
ASDF_DIR=/Users/howard/.asdf

Verify that $myvar is not exported to the calling shell. Here we see that the exec-env script is still called at the end of the echo invocation. It's not clear to me what's invoking this.

$ echo $myvar

exec-env: $0 is /Users/howard/.asdf/bin/asdf
exec-env: args are java zulu-11.48.21 run_within_env
exec-env: Running in bash
ASDF_INSTALL_VERSION=zulu-11.48.21
ASDF_INSTALL_TYPE=version
ASDF_INSTALL_PATH=/Users/howard/.asdf/installs/java/zulu-11.48.21
ASDF_DIR=/Users/howard/.asdf
vic commented 3 years ago

If I recall correctly, using the bin/exec-env is the documented standard way of doing it. Not only because it's loaded before each shim execution, also there's an asdf env command that exist exactly for this purpose: allowing external tools or shells get the correct environment variables as exported by the plugin.

So, for example people or IDEs could use asdf env java to get the right environment. And also other plugins like asdf-direnv which depend on the environment as exported by bin/exec-env, instead of each plugin having a custom script where they export their variables.

howardburgess commented 3 years ago

Thanks @vic for the clarification. For some reason I had missed that asdf env existed as a subcommand.

asdf env <command> [util]               Runs util (default: `env`) inside the
                                        environment used for command shim execution.

Looks like a worthwhile approach then.

❯ echo 'export myvar=myvalue' > ~/.asdf/plugins/java/bin/exec-env

❯ asdf env java | grep myvar
myvar=myvalue
joschi commented 3 years ago

https://github.com/halcyon/asdf-java/pull/148

Kaylebor commented 3 years ago

Should we update or delete the old scripts?

We could replace all of them with the following code in the user's .zshrc or equivalent:

export $(asdf env java | grep JAVA_HOME)