-
-
Notifications
You must be signed in to change notification settings - Fork 268
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
Project.jl as an extension to Projec.toml #1828
Comments
This reminds me of installing Python packages. When you install a python package, it can run basically any code it wants. This makes installing Python packages a nightmare. Personally I do not like the idea of running arbitrary code when I instantiate a project. |
You can run any code in Julia too. Not having this option means that people will run these stuff inside their This:
The limitation is not desirable all the time. Sometimes people want more flexibility, and not having that results in undesirable things that are very hard to fix later. Running the code is already allowed by the Side thing: not having this option does not help security. See here. |
Dependencies and features should be declarative. If we want OS/VERSION dependent dependencies or unregistered dependencies then that would be added by adding syntax for it to the existing Project file, not by running some script file where things are queried. Interactive things during package install strike me as particularly bad. In general, I would say we want to move more things towards more declarative and less arbitrary code style (cf the artifact system over the build scripts) so this would be a step in the wrong direction in my opinion. |
100% agree with @KristofferC. Arguing that making things less declarative somehow makes it easier to statically compile things doesn't make sense to me. |
If you can give me solutions for the things I said in this issue, I would appreciate it! Personally, I will abuse
I don't understand why Julia is different here... @KristofferC. Pkg.add adds deps to the Project.toml. What is the difference here? Even if it edited the Manifest, static compilation mostly should use Manifest.toml, not Project.toml. You want all the dependencies not just the direct ones (unless wanna do incremental compilation). When you have all the code in init, you can't do anything.
That was just an example of the possibilities! I would use global parameters and |
@staticfloat has opened some good issues and pull requests regarding this kind of stuff. The goal is to eventually make package directories completely immutable. This is possible with a combination of:
I think that all of the stuff you want to do can be covered by those four. For example:
If there is something that you want to do that is not covered by |
Also, for what it is worth, (and this may be off-topic): I think it would be cool for us to eventually completely remove I am hoping that this will be possible eventually. But I will let @staticfloat correct me as to the feasibility of this. |
Let me explain why doing package operations like
or
in a generic post-script hook is not such a good idea. The way Pkg (and many other package managers) works is that they gather up all the packages you want to have installed and what compatibility bounds they have as well as all packages and versions it knows about (from registries) and sends this to a "resolver". However, if you run another package operation as a part of the installation of a package, you call back into the resolver to give you a new set of versions. Those versions might be different than in the first resolver call because the package you added in the post hook can introduce new compatibility bounds. So now you are re-running the resolver and might install new packages which might have their own post-installation hooks and might do Pkg operations calling back into the resolver etc. It seems likely that you can even end up in cycles here where you are just spinning around running post-installation hooks forever. Therefore, we want to be able to up-front gather all packages that are going to be installed so we only have to run the resolver once. This is done by e.g. making sure that we know what dependencies and compat info packages have without having to execute arbitrary Julia code. |
Yes, that would be great. Not sure if we'll ever be able to fully get there, but we want to at least eliminate as much non-declarative package setup as possible.
Allowing people to run arbitrary code when installing, configuring or setting up packages is certainly the easiest thing to do form a design perspective and it's very seductive. I suspect that's why so many systems do it—it's easy and maximally flexible. But it really ruins reproducibility, predictability and portability. If you run arbitrary code that can look at anything on the system it's running on when configuring or installing a package, then how to even install a project implicitly depends on all of the global mutable state of the environment it happens to be running on. If arbitrary code can be run to determine the dependencies of a package, then it's not even possible to definitively say what a package's dependencies are 🙀 Most of Pkg work in 1.0 and since has been in the exact opposite direction of this: we're trying to make as much of package installation and setup declarative and immutable. This proposal does the opposite and thus is antithetical to the philosophy of Pkg. |
Another point: CMake is a build system not a package manager. Build system have to run code—that's how you build things. That's a totally different situation. Conan is a package manager but it invokes an arbitrary build script, so it makes sense it would also allow arbitrary execution; they're just not in a position to constrain things more even if it would be beneficial. Rust is/has a build system, not a package manager. I don't believe that Cargo actually lets you run arbitrary code to determine what the dependencies of a package are. Even if it does, that doesn't mean we should. |
One of the primary things that impeded making my Because you can't know what packages need to be installed beforehand, you end up with longer install times (you can't fetch all packages in parallel, you have to fetch some packages, start installing them, then go fetch the dependencies that are missing from those dependencies, start installing those dependencies, and recurse), and you end up needing to actually set up every environment that you'd want to be able to install into, rather than being able to just collect everything you need for all platforms from the get-go. The Pythonistas know this is an issue, and they're moving toward a fully-declarative model with |
Not only is this slow, but it means that Python projects can't actually do version resolution correctly for reasons like what @KristofferC described. You need a fully dependency graph in advance in order to do version resolution—and even with that graph, it's a non-trivial problem. If you have to run code for a version to find out what the dependencies are, that means that to do proper version resolution, you'd have to run the code for every single version of any package that you're considering installing, just to find out what it depends on and then run the setup code for that, and so on. All just to get a graph that you can use to compute which versions of which packages you actually need to install. This unfortunate design choice in |
It would be nice if we can have a
Project.jl
as an extension toProject.toml
in our root directory to perform custom things that are not covered inProject.toml
.Pkg.instantiate()
should run this file after it processesProject.toml
.Some use cases:
Interactive experience
Dependency based on the VERSION or OS
Unregistered packages
I might want to add a dependency that is not registered yet. I can simply do it in the Project.jl file.
Adding compat methods based on the VERSION or OS
Custom script after installation
Run the tests after installation
and many other examples.
This is similar to
deps/build.jl
, but being in the root, separates the Pkg and init stuff from building.The text was updated successfully, but these errors were encountered: