sdkman / sdkman-cli-native

The next generation of SDKMAN! CLI commands, written in Rust
Apache License 2.0
129 stars 14 forks source link

Will there be a native version of `sdk`? #189

Open tillig opened 11 months ago

tillig commented 11 months ago

I use PowerShell as my main shell, so things like shell functions in bash don't really work so well. Is there a plan to have a replacement for the main sdk command in native format so I wouldn't need the shell functions?

davidkron commented 11 months ago

I'd hope so. As a quasi-standard tool in the JVM ecosystem, this should have already been implemented years ago. Especially since the JVM ecosystem is a major player in platform independent development it is a shame that one of the major platforms gets ignored for years.

marc0der commented 8 months ago

Hi @tillig, unfortunately we don't (and won't) support power shell, as it is not a universal shell. However, bash is available on all platforms including on Windows through WSL and even MSYS.

The native extensions in this project are already being used on Windows if you are using either of the above. You can confirm if you have them by looking under .sdkman/libexec. That said, you will always need a bash shim to propagate environment variables to your shell environment.

tillig commented 8 months ago

PowerShell is supported cross-platform and has been for years. I'm not sure what constitutes a "universal shell" but if bash is it, then I guess that's it. Mashing WSL/MSYS together with a native Windows environment has not been very successful for me in the past, hence the suggestion to provide a native executable rather than bash scripts. I've seen this done for a lot of tools out there and it seemed not unreasonable to ask about.

marc0der commented 8 months ago

this should have already been implemented years ago.

@davidkron nothing should have happened, we operate under the Apache 2.0 license, and so have zero obligations to anyone. We are all volunteers who do this work in our own spare time.

it is a shame that one of the major platforms gets ignored for years

There is no shame here, as we've supported Windows from day one. We just don't support any proprietary shells like Power Shell. Feel free to install WSL or Git Bash (MSYS) on your machine to see SDKMAN in action.

You can get instructions for installing on Windows in the Windows Installation section on the install page of our website.

marc0der commented 8 months ago

@tillig I totally get that, and we did have a power shell version in the early days (called PoshGVM). Sadly it was never maintained and was eventually discontinued.

Also, I don't know anybody that uses Power Shell outside of Windows, yet I know many developers that use bash. Perhaps give WSL another try, as it offers seamless integration with unix.

tillig commented 8 months ago

Again, cool. Just thinking if it wasn't shell-specific at all, then it wouldn't matter what folks use. 🤷

marc0der commented 8 months ago

I tried doing it that way early on in the life of this project, but all JVM tools need an environment shell to run in and are dependent on environment variables such as JAVA_HOME in that shell. That's why we always need that shell layer to export these variables. If you ever have the appetite for it, you could contribute a Power Shell shim around the native components that we ship.

Also worth noting is that the native exertions are a work in progress and don't cover all the commands yet. Hopefully, that will change during this year!

tillig commented 8 months ago

Since you'd have to execute the native command from inside your own shell/terminal, the environment would be there already (agnostic of the shell). What I was hoping this sdkman-cli-native project would be is a native Rust-based replacement for the whole of sdkman. I noticed things weren't complete, so I figured I'd ask. However, if it's going to be bash + Rust, it won't solve the issues I have, so I'll have to look elsewhere. Which is totally fine, absolutely, just slightly disappointing.

I have lots of folks (maybe a couple hundred?) doing cross-platform scripting (Windows, Mac, and Linux) in Powershell for builds and application management. We have some security requirements that stop us from being able to use WSL. MSYS bash intermixed into other scripts and tools (shell calling shell calling tool calling shell sorts of things) is not necessarily fall-down-easy to set up; and generally results in spending too much time troubleshooting individual machine configuration issues. Shell-agnostic tools are easier for us to get folks working with en masse.

But that's maybe neither here nor there. Just saying, my experience differs from yours (I do see a lot of work with Powershell outside Windows); and precludes some of the things one might think to be "simple" in other environments.

I'll keep my eye on this project to see how things go to determine if it's something I can POC for the team as it develops.

marc0der commented 8 months ago

In that case, it makes even more sense for us to start supporting Power Shell in the future. We always welcome contributions, so perhaps you could convince your company to spare some resources to contribute the PS shim for the greater good!

codespearhead commented 5 months ago

I'd hope so. As a quasi-standard tool in the JVM ecosystem, this should have already been implemented years ago. Especially since the JVM ecosystem is a major player in platform independent development it is a shame that one of the major platforms gets ignored for years.

Although I agree with that comment, it cannot be overstated that a significant portion of the world depends heavily on projects managed by either a single person or a very small team of about half a dozen people.

[A tower of blocks is shown. The upper half consists of many tiny blocks balanced on top of one another to form smaller towers, labeled:]
All modern digital infrastructure
[The blocks rest on larger blocks lower down in the image, finally on a single large block. This is balanced on top of a set of blocks on the left, and on the right, a single tiny block placed on its side. This one is labeled:]
A project some random person in Nebraska has been thanklessly maintaining since 2003

Remember the Log4j fiasco? What about the recent XZ Utils one? Axios HTTP was virtually dead until a group of volunteers and dependent companies intervened to revitalized the project in the last three years, elevating it to one of the most-starred projects on GitHub.

While financial contributions do incentivize maintainers, money alone is generally not the primary motivation; otherwise, it would be more financially sensible for maintainers to avoid unpaid work altogether. That's why activities like reviewing PRs, as well as raising and triaging issues, are crucial for the project’s health. Indeed, multiple heads think better than just a few, don't they?

codespearhead commented 5 months ago

I tried doing it that way early on in the life of this project, but all JVM tools need an environment shell to run in and are dependent on environment variables such as JAVA_HOME in that shell. That's why we always need that shell layer to export these variables. If you ever have the appetite for it, you could contribute a Power Shell shim around the native components that we ship.

Also worth noting is that the native exertions are a work in progress and don't cover all the commands yet. Hopefully, that will change during this year!

BASH software is hard to maintain, primarily because testing tools are virtually non-existent. Scripting languages such as JavaScript and Python boast a vast ecosystem, but they require an interpreter. Rust and Golang are strong contenders, but the real question is whether their complexity, alongside their relatively young ecosystems and limited community, is worth it for the project's use case.

I wonder if you'd have any objections or concerns about having the next version of the project written in Java with PicoCLI, compiled to native binaries via GraalVM and released via GitHub Actions. It's worth noting that JBang already uses PicoCLI.

reitzig commented 3 months ago

@tillig The thing is that sdkman modifies environment variables, and that act is specific to each shell.

When writing sdkman-for-fish, I faced basically the same challenge. It's possible to wrap around Bash-y sdkman, if gnarly. I hope that sdkman-cli-native will make that easier, eventually, but it's too soon to tell.

Point is, as long as you have some way to run Bash-y sdkman, capturing its modifications of env vars should be possible for Powershell in a very similar way as I use for fish.

zerosign commented 2 months ago

Is there any (technical) blocker/merits for the sdk binary to be just being coded entirely in Rust instead of wrapping multiple binary (uninstall, home, help, version, default) using bash ? (will there be a plan for this?)

marc0der commented 2 months ago

@zerosign as explained above, tools require environment variables like JAVA_HOME to be exported, which can only be done by a shell script running the export command. This is why we need a shell script wrapper around the Rust binaries.

Perhaps you know of a way of working around this problem, so please share if you do.

codespearhead commented 2 months ago

From what I've seen, there seems to be no cross-platform library to manipulate system environment variables in any programming language.

For SDKMan to be rewritten entirely in Rust, does it just need an abstraction to read from and write to system environment variables?

reitzig commented 2 months ago

As far as I can tell, sdkman could be wrapped much like asdf, mise, venv, and similar, e.g.

sdk env | source

provided the output is something like

export PATH="...:$PATH"
export JAVA_HOME="..."

in the format matching $SHELL.

If that was the goal, some externals might need to change. Commands like sdk use won't work with a one-time setup as-is.

One could also conceive of every sdk command writing the env-code to a stream or file separate from the normal output, for a shell wrapper to be pocked up in a similar way as above.

zerosign commented 2 months ago

As far as I can tell, sdkman could be wrapped much like asdf, mise, venv, and similar, e.g.

sdk env | source

provided the output is something like

export PATH="...:$PATH"
export JAVA_HOME="..."

in the format matching $SHELL.

If that was the goal, some externals might need to change. Commands like sdk use won't work with a one-time setup as-is.

One could also conceive of every sdk command writing the env-code to a stream or file separate from the normal output, for a shell wrapper to be pocked up in a similar way as above.

Cmiiw, if that's the case maybe sdkman only need to output fish/bash/zsh export vars in their respective native scripting format thus, people could complement using something like direnv ?

Trying to summarize here, cmiiw, so that means sdkman doesn't need to be wrapped in scripting lang and can be rewritten full in Rust?

reitzig commented 2 months ago

Well, skd use needs a shell wrapper unless internals change a lot.

For instance, aqua uses shims and a proxy binary that inspects config files to account for folder-based differences. That way, PATH never has to change -- but there are disadvantages, too.

reitzig commented 2 months ago

FWIW: Personally, my dev setup has evolved beyond JVM-only and I use mise (for SDKs/runtimes) and aqua (for tools). From this perspective, it might be preferable to integrate sdkman into mise (or a similar tool), as plugin or backend. Why implement your own frontend if you can piggyback, amiright? 😉

marc0der commented 2 months ago

I'll be honest to say that this is not likely to happen. It would be extremely disruptive for our users who are perfectly happy with how it is right now. Our users don't care about what it's written in as long as it works. Most of them are blissfully unaware that they are using our rust binaries, and that's how I want to keep it. I think the wrapper script will be staying for quite some time until the command migration to rust is complete.

reitzig commented 2 months ago

To be clear: completely fine by me. I'll be happy to shrink down reitzig/sdkman-for-fish:conf.d/sdk.fish to a handful of lines!

marc0der commented 2 months ago

I love it. Less code to maintain, and maybe in the future, nothing at all! I also look forward to deleting lots of superseded bash functions soon :smile: