-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Discussion] How to handle multiple languages with the CLI #513
Comments
The central conflict seems to me to be between doing it in the most correct way vs doing it in a way we have the ability to maintain. By which I mean: creating the CLI in every language seems like the canonically correct approach, but I don't think we have the resources to actually create and maintain that many CLIs. |
What languages are we supporting and how are we keeping the binaries up to date? The basic run a command and copy everything action could easily be duplicated for all languages. A binary cross compile of c extension or whatever is a taller oder. Even then I don't see why many cli's are needed. That seems like a lot of duplicate code. I think a standard abstraction and breaking it out into plugins might be a good approach. I also don't think that we need to fully serve every language like we serve JS. |
We stated that we would support Rust and Python. I think plugins that we can submodule make it more feasible to have the community that is excited about any particular language have ownership over it rather than relying on our small team to cover more bases. Certainly, a separate CLI would have the same effect. |
I'm completely unfamiliar with any of the technological progress which has enabled the t2-cli to work. With that in mind, the following is entirely based off of intuition, please disregard as necessary. THE HOLY GRAIL GOALLet every user plug a t2 into their computer, install the CLI using their favorite package manager (mine is npm, some people like apt, others brew or yum, still others like gem, pip, crate, and cargo), and deploy A SOLUTIONWhy not create the CLI's internals in a portable language, and deliver that, both as a binary and as a library which can then be integrated into every other language we support through Foreign Function Interfaces? Adding a new language then becomes straightforward:
DetailsCreating a portable CLI libraryWe can write most of the CLI in Rustlang, which also offers itself up nicely for bare metal optimizations from embedded systems geeks. Rust loves FFI: https://doc.rust-lang.org/book/rust-inside-other-languages.html Furthermore, the CLI could then be wrapped in a daemon process in order to power tools such as an automatic firmware / device flasher or a Tessel2 cluster status reader. A similar approach can (and maybe should?) be used to give tessel and USB module support to every language we want to add. In fact, I think you're already doing something similar with the connection between OpenWRT and the IO Coprocessor. Deploying the command lineEvery attempted installation should try to put the Every language I've briefly mentioned has some ability to install related dependencies. A worst case example: when you install an I also found a python package which allows you to distribute rust extensions for python: https://github.com/novocaine/rust-python-ext So long as the main CLI plumbing is in the same place, creating language specific CLI's would be a simple act of creating glue code via FFI, IPC, or simply by shelling out, the way the CLI mostly just runs shell commands on the tessel2. THE TESSEL COMMANDScenarioIdeally, I should be able to deploy a project which is a mix of JavaScript and Rust to a tessel, so that I can have good network interfaces (socket.io...?) combined with good bare metal performance without waiting for Crankshaft's optimizing compiler to kick in. The codebases communicate with standard linux inter-process communication (ipc), and the codebases manage the named pipe (or whatever)'s location. rustlang: http://alexcrichton.com/ipc-rs/ipc/index.html Example ExecutionThe new tessel command would do the following:
The tessel then starts the processes in parallel Final AnalysisWith this approach, the tessel CLI becomes a consistent platform which is scriptable from other languages. Sensible conventions should allow the tessel command to work with almost any language, given a suitable package.json. Furthermore, language specific idiomatic interfaces can be easily created and then installed using the language's favorite dependency manager. There are drawbacks, of course. We've already written the command line in JavaScript. Throwing that work away and starting from scratch only makes sense if we can make the new CLI 5-10x "better" at achieving our goals. Many lessons have been learned through writing the CLI twice, though, and we should have a pretty good estimate of what we're doing before we do it, which speeds along porting quite nicely. I don't want to write this in C, but Rust is an evolving language. Since the t2 is a JS microcontroller, I don't think this matters. There's increased complexity in management, and in communicating with end users if something goes wrong: $ pyssel run
Warning: There is an updated tessel command line.
Warning: New goodies: cloud deployment
Warning: Please run `pyssel update` to update to the new CLI
Warning: If you use multiple tessel command lines (russel, pyssel)
Warning: You will need to update each in order to use new features
$ pyssel update
Updated tessel CLI to version 1.3.4
$ cd ../rustproj
$ rustel run
Warning: There is a difference between your rustel version and your tessel CLI version
Warning: All your commands will still work, but you're missing out on goodies
Warning: New goodies: cloud deployment
Warning: Please run `rustel update` to update to the new CLI
$ cd ../rubyproj
$ russel run
Error: There is a breaking change between your russel version and your tessel CLI version
Error: This happens when you update that tessel CLI without updating russel as well
Error: Please run `russel update` to update to the new CLI My only contributions to tessel have been to the CLI, which was simple enough that I could get started immediately and bang out in a few hours. Making the CLI more complicated and writing it in Rust makes this much harder for our audience to do. The Big Problem I Forgot AboutThe largest problem I can see would be defining a language agnostic way of deploying codebases to the tessel, such that one underlying tessel command can interact with rust, ruby, or nodejs. It makes sense to use language specific "plugins" to handle steps such as compilation. Ideally, that "plugin" would be built into the language specific CLI, such that In this way, "languages" { "rust": {"root": "math", "cmd": "rustel", "standard": true }}, Wherein root is the source root, cmd is the name of the command that tessel-cli should communicate with, and standard is a boolean flag which says that the rustel API is a superset of the tessel API. |
@MrNice Creating a cross platform
Just to make sure I understand, you're trying to tackle the problem of deploying a Tessel application that has dependencies in multiple languages? |
I deprecated my usb crate because another project surpassed it: https://github.com/dcuddeback/libusb-rs. It should have everything you need. |
Ah, thanks @kevinmehall my meager Googling couldn't find a Rust USB lib. |
@kevinmehall Awesome! @johnnyman727 I want to not write rust code when I add BASIC support to tessel. I want to, at most, write BASIC code that interacts with the rust code. I'm willing to at least write out JSON which describes how to deploy and run BASIC code. A JSON DSL, like Grunt or npm or any number of other tools use. I don't know enough about the current deployment strategy to say, "Oh, it's already language agnostic, we just need to expose four knobs; one for the interpreter, command arguments, source location, source destination" |
@MrNice I think we could to that by giving the standard library a callback to execute once we're ready to deploy code (ie a language plugin). Each language will be responsible for how it compiles, deploys, and runs, etc. The standard library can expose the same sort of |
Could we have a more modular interface, like that of the git command? Then the communities can write their own deployers, and other interaction pieces. |
@johnnyman727, I wasn't thinking a library. With git there is a single command and you can create any executable and name it |
Here is someone talking about building git extensions. = |
I'm specifically saying: Build a cross platform library, then wrap it in a The "modular interface" refers to how the Git command line api is I'm against 'tessel python init' 'tessel python run', and for 'tessel init I spent a lot of time talking about hypothetical commands like "pyssel" I currently hate the idea of a pyssel command. On Wed, Jan 20, 2016 at 5:01 PM, Jon [email protected] wrote:
|
I don't understand why npm would be used to distribute a Rust binary, when clearly Node.js is installed on said machine—otherwise npm wouldn't be installed. |
I'd like to re-open this conversation and accelerate development in other languages (driven primarily by my interest in Rust). I agree with @MrNice that a portable CLI library that can be used by any other wrapper language would be ideal and it's certainly a great goal. For now, I think we should use the same CLI (installed via
This process would allow us to start building out more language support immediately but provide us with a roadmap to the best use experience for each language. |
Sure, a
I'm going to be blunt here: this reeks of second system syndrome and will certainly serve to hurt the progress of the existing code bases (by disproportionately demanding time and effort). If I had known that a year's worth of work was going to be tossed out like this, I would've found something else to do with my time. This also means that a certain section of current maintainers are excluded, to some degree, from participating in future development. |
The benefit is certainly difficult to quantify but I've heard a lot of excitement from the Rust community about T2. If the community rallied around Tessel as the embedded platform for Rust, we could potentially grow the community much larger. This could bring in contributors who not only work on Rust-specific code but the CLI as a whole and that benefits everyone. Plus, I want to learn Rust and this is a good way for me to do it while continuing to engage with the project :)
Yes, I agree about second system syndrome. But the hope is that it would be resolved by eventually splitting it back up into language-specific CLIs. It's only temporary to bootstrap the effort. In the meantime, I think we can pretty well sandbox the deploy stuff so that JS users don't have a worse experience because of it.
Rewriting a bunch of the CLI into an executable is a pretty significant undertaking that is probably more work than the original CLI was. I imagine it would take a long time to get this done such that even if we did, the CLI written as it is, is still a critical stepping stone. By building on top of what we have now, we can let the community experiment with Rust immediately which is super valuable, in my opinion. Rust hadn't even hit 1.0 when we started work on the CLI- Getting the chance to build a cross-platform executable simply would not have been possible if we didn't invest in a Node-based CLI first.
Yes, I agree. But I think if we have the core working really solidly, there will be lost of other things to work on in JS. But yes, I agree we could be excluding some people if we swapped in an executable. |
I'm going to recap my assumptions and work from there
My driving goal: I suggest this, without committing my own hours:
This satisfies Jon's wish to play with rust more and lets us do a real In response to rwaldron: The second-system effect (also known as second-system syndrome) is the The goal with having an executable is to create a small, elegant, and cross Every bit of work put into the CLI to date has been immensely valuable and Thanks for listening! On Tue, Apr 26, 2016 at 1:27 PM, Jon [email protected] wrote:
|
I'm very aware of this fact. Have you considered that you will need to rewrite every cli dependency?
Considering my last point, I don't know if you realize how long this will actually take.
I don't understand what you mean by this? Are you going to make another project that just delegates to
Given 3, who will spend the months, possibly years, building 4?
My kindest advice: don't ever lead with this when asking others to take on some massive amount of work.
Thanks for the passive aggressive attempt at a correction, accompanied by a link to the wikipedia definition of "elegant"—you've succeeded in alienating me from your cause. |
For the CLI or for programming on the T2? Are you conflating these two, completely different contexts?
Given my previous question, it's unclear to me what this library does. |
Interjecting in a moderator role - please remember to be kind to one another in this and every thread. It's easy to misinterpret intent on the internet, and even easier to make a place unfriendly out of frustration. Keep it constructive. Seek mutual understanding. Make this a good place to be :) |
My thoughts on the subject: We're anticipating a solution to a problem that hasn't actually surfaced. I'd like to let user needs drive our design, particularly given resource constraints. Let's go for the quick fix (since I think you have a mostly-working solution there, right @johnnyman727?) and then build out more "proper" tooling if there is demand for it - and particularly if there is some champion within the community who wants to lead that. |
I probably don't appreciate how long it would take. The good news is that the Rust ecosystem is building out very fast so there are a lot of libraries we could make use of. We would not have to rewrite all dependencies but likely a few of them. Also, the only way I can imagine we would bootstrap a community of Rust devs together willing to invest in building an executable is if we release something immediately useful rather than an abstract goal.
I mean building out Rust-specific deployment logic (and project initialization) that is part of the Node project. So Rust devs would need to have Node/npm installed but could use There are folks asking me if they can use Rust on Tessel right now so it would be great if we could start merging related PRs like #292 and #511 (after cleaning it up). @kevinmehall mentioned that he also wrote the equivalent of |
#511 is a non-starter in it's current form |
@rwaldron 100% agree. I was just making a proof of concept. I have a lot to clean up. |
This is based on a conversation i had with @johnnyman727. |
Thanks for the additional proposal @tikurahul, I'll follow up there. I'd like to reach a consensus on whether or not we should start building additional language support into the JS API as a first step. I would start by adding Rust and I propose we use it as a trial of sorts. If it doesn't go well and/or puts the JS experience in jeopardy, we can revisit the issue. @rwaldron I don't think we have explicit agreement from you. Would you be okay if I got started on my proposal? |
We've laid down the framework for adding more languages since the recent addition of Rust. I'm going to archive this conversation for now but thanks to everyone who contributed! |
I recently started investing more effort towards using Rust on Tessel 2. After opening a preliminary PR (#511), @rwaldron brought up some concerns about the code getting too complicated. I wanted to open up a general dialogue about how we might handle multiple languages being deployed to T2.
My initial thought was to use this existing
t2-cli
to deploy code for any type of language. The rationale is simple: because deployment is only one of a handful of actions one might take upon a T2 (among wifi configuration, listing available Tessels, setting up access points, erasing code, etc.). It doesn't seem like much of a stretch to me to have one similar code base and then as soon as code starts being deployed, we detect the language and route the rest of the deployment to a language-specific process. For example, in pseudo-code:To be clear, I don't mean that the deployment of any other language is a separate program written in that language - I just mean that we have a separate piece of JS that deals with it (because some languages have compilation steps and different ways to run the code).
The downside is that we have more deployment code to maintain and it continues to grow as we support more languages. Another downside is that folks coming from a specific background (like python) might expect to download the tool using that language's package manager (like pip).
@rwaldron suggests we have a CLI written in every language that is supported on the Tessel 2. So, if we want to support Rust, we would need to write a CLI in Rust that supports all the same actions this
t2-cli
supports. That way, Rustaceans (or Pythonitas or whatever) can interact with the CLI in a way that is more idiomatic to the language at hand and we keep each CLI deployment code more simple.I'd love to hear other thoughts and/or suggestions on the topic!
The text was updated successfully, but these errors were encountered: