-
-
Notifications
You must be signed in to change notification settings - Fork 269
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
Applications: what are they? #1962
Comments
I think this is a bit related to what I was working on. CLIs can be one kind of the applications, since in principal they can be built in a standalone environment using PackageCompiler as an app, and then installed to |
Posting this discussion here: https://discourse.julialang.org/t/julia-bin-as-a-standard-location-for-scripts/45993. Some quick thoughts/ideas. The exact name of stuff are not that important.
Qustions:
|
I've been thinking about this for a while, so herewith some comments. I agree with most of #1962 (comment) except:
Some other random comments
|
Maybe there should be a library version of |
I was actually thinking about this this morning, funny coincidence. This is what I had in mind, and what I sketched up now:
whereas in the regular env
Edit: version 2:
|
I entirely agree with Kristoffer's comment above. Some thoughts about the remaining questions:
I'd say yes, just clone it. Then with the minimal interface defined above:
Or possibly
if the scripts in
I think this would be useful. Perhaps via environment variables? A related question is whether there would be a way for the app itself to control which command-line arguments are used for the Julia process that runs it. Apps could perhaps declare a preferred (poossibly overrideable) set of arguments in
I don't have any sensible answer to propose here, but just wanted to mention that this question is very important if we want to allow "executables" to support custom sysimages. I guess what makes this particularly difficult is that some users delete older julia versions when they install a newer one. Others don't but update a set of symlinks in their PATH so that older versions remain accessible, but under an other name... Maybe a minimal way to handle julia upgrades would be to provide a way for users to re-generate all wrappers in |
I recently have been building some CLIs which I think are also "Applications". I agree with most of the comments above, but the current solution I'm using now is a bit different from what @KristofferC described, which might be interesting to consider.
In my case, the CLI projects are generated by the DSL Comonicon, it generates an entry function
#!/bin/sh
JULIA_PROJECT=/Users/roger/julia_code/IonCLI /Applications/Julia-1.5.app/Contents/Resources/julia/bin/julia \
-J/Users/roger/julia_code/IonCLI/deps/lib/libion.dylib \
--compile=min \
-O2 \
--startup-file=no \
-- /Users/roger/.julia/bin/ion.jl $@ I guess potentially, I can also generate an entry file in
I implemented this in Comonicon: https://github.com/Roger-luo/Comonicon.jl/blob/master/src/tools/build.jl#L559 in case if someone wants it. Regarding environments, I'm currently using the package environment directly with a committed
I think allowing developers to config in
I think this currently works for me. but note in my case if I want to generate the entries in
I'm using the julia when the user install the application/package. so at least we can make sure this julia executable is compatible (guaranteed by Pkg) and can run/build the application.
I think in rust, application names are registered so at least in the same registry you can't have two same application names. |
I thought about this some more and I don't think this is "correct". Firstly, we should have a "manifest" file that lists all the applications that are installed. This should be a TOML file and should contain all data that is necessary to reproduce the same set of applications on another machine. It could look something like
so in this case, running We could then have something like There would then be a set of Pkg commands that manages this file. For example:
Pkg always makes sure that the stuff in |
Yes, I agree that the application needs to support precompilation so it should probably be something like
Do you mean that apps want to set custom julia argument options themselves. Maybe that should be in the project file then. Users could override them with something like:
where everything after
But we also want to be able to just add an application by url á la |
@KristofferC does this mean per environment I feel the
One potential issue is that if the application is itself a CLI application, these extra options might not be necessary and can make the already complicated CLI more complicated.
If it's not a registered package, maybe user should take their own risk? if we have per environment |
Here's my take on how to define an application:
The format of name = "MyApp"
uuid = "..."
authors = ["..."]
version = "X.Y.Z"
[executable.app_1]
package_name = "MyPackage"
package_uuid = "u-u-i-d"
entry_point = "app_1" # i.e., `MyPackage.app_1(::Vector{String})` exists
[executable.app_2]
package_name = "MyPackage"
package_uuid = "u-u-i-d"
entry_point = "app_2" I think it's nice to decouple how an application is specified and how it is implemented. For example, with this approach we can also derive in-REPL Pkg-like "CLI" from the above interface (i.e., just install MyPackage and call
If we enforce that an application has no code, we can just dev a package that implements the application.
If the entry point is easy to import as a function, you can just call it with |
I don't really understand this. It seems odd to me that a set of entry points can go into different packages and that they are in packages listed in the manifest and not the Project.toml/Application.toml. What if I don't want to register a package, the code my app executes might be only for the app and is not reusable as a library? I think each application should have an associated module that can be individually precompiled and where app code can be put. Depending on the entry point you might want to load a different set of dependencies. So an app with multiple entry points would be structured something like
# Application.toml
name = "MyApp"
uuid = "..."
authors = ["..."]
version = "X.Y.Z"
[executable.App1]
# metadata
[executable.App2]
# metadata
[deps]
DepA = "..."
DepB = "..."
DepC = "..."
...
# src/App1.jl
module App1
using DepA
using DepB
main(args::Vector{String}) = ...
end # module # src/App2.jl
module App1
using DepA
using DepC
main(args::Vector{String}) = ...
end # module The user facing entry points would be |
My point is that code is usually reusable. If the entry-point function does not call That said, what I'm proposing is doable by suggesting # src/App1.jl
module App1
using MyPackage
main(args) = exit(MyPackage.app_1(args))
end # module as the best practice. I just thought that it's nice to encode the best practice as the default behavior. |
Maybe, maybe not. If the user wants to not deal with the overhead of writing library like code that should be totally fine. Forcing all application code into a library might very well mean that nice tools don't get made because the author doesn't think the code makes sense in a library (and maybe it doesn't). One should be allowed to write cool and interesting applications that are not meant to be used as libraries without having to register some dummy library package. |
Since Manifest.toml file can contain URL and relative path, I don't think that's necessary.
Do you mind elaborating on this? Frankly, I don't understand why categorizing a certain set of files as "library" instead of "application" suddenly makes it hard to write exactly the same chunk of Julia code. This is especially so when you don't have to register the package. |
That's a good point and then the difference between library and application code becomes moot. But then I don't see what you object with to e.g. the layout in #1962 (comment). Instead of
you want it to be
and each "app" runs |
Just one related thought on this, if there is a registry for applications, then we can consider provide an option to compile the entire application as standalone executable on registry side, and even Julia itself can be one of the application on this registry. Thus should make download of a lot Julia toolchain become easier and user don't need to wait for precompile/compile locally. |
The main point I wanted to emphasize was that having a package-compatible directory structure reduces the things Julia programmers have to learn and also infrastructures such as Pkg.jl have to implement. If the code lives in a separate directory or a URL, Julia programmers don't have to learn anything for knowing how to
Actually, I want
so that I think it resembles the move from |
Ok, that is a valid point that I can agree with. In fact, PackageCompiler.jl apps are structured in exactly that way. I'm not sure what it means to have multiple project files but one manifest file. How would the resolution process for that work? What happens to |
It would be cool but also require a significant amount of infrastructure and work. You would need buildbots for the different architectures, automatic hosting, a download page for apps etc. |
Hmm..., I thought it'd already work out-of-the-box. I'm thinking that the top-level [[App1]]
deps = ["Compat"]
path = "App1" # relative path
uuid = "945464c1-6d4c-46d5-ac5e-fb453f79302f"
[[App2]]
deps = ["JSON"]
path = "App2" # relative path
uuid = "32a02d8f-a56a-4e64-b0fa-04f84568876c" and name = "App1"
uuid = "945464c1-6d4c-46d5-ac5e-fb453f79302f"
[deps]
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
[compat]
Compat = "2.0, 3.0" I thought For more advanced usages like using |
I guess this is something related: so I'm providing standalone binaries via PackageCompiler and GitHub Actions for CLIs made by Comonicon. This is done automatically, but it can still be cumbersome to install these applications. Since they are standalone, I might expect that users may not have a valid julia compiler locally, thus I provide a shell script for a one-click installation experience: https://github.com/Roger-luo/IonCLI.jl/blob/master/setup , so users can install an application like this directly via
so I notice there is https://sh.rustup.rs in rust community, I'm thinking if we could have something like |
It seems to me that what is being discussed here does not square with "Application" as defined in the glossary: "Application: a project which provides standalone functionality not intended to be reused by other Julia projects. For example a web application or a commmand-line utility, or simulation/analytics code accompanying a scientific paper." (emphasis mine) As for simulation/analytics code, I don't need any command-line tool installed. So, maybe there is a need to add another term to the glossary, something like to "a-bunch-of-scripts". So a project could be a Package, an Application, or a-bunch-of-scripts. As far as I can tell, most of what's discussed here does not apply to a-bunch-of-scripts projects. |
what does a-bunch-of-scripts projects look like typically here? is it still a Julia project? or just a folder of scripts? |
I don't know if it's typical, but I recently made this, which has a julia package structure, but also a |
Yes, something like this. Although mine look a lot less fancy than @kescobo's ;-) But the Project.toml & Manifest.toml are essential to keep track of the deps, so it's a project. Edit: this https://github.com/luraess/julia-parallel-course-EGU21 would be a good example as well. It's not for a paper but a course with a bunch of scripts which the students can then run. |
I kicked off a related discussion on discourse:
I'm sure there are lots of things I'm missing here (e.g. would this approach work on Windows? how to handle things like header files for libraries?), but I would be keen to hear other people's suggestions. |
I've put together a minimal prototype of my idea here: https://github.com/simonbyrne/PkgApp.jl |
I want to start an official discussion of what makes a project an application here.
The text was updated successfully, but these errors were encountered: