ziglang / zig

General-purpose programming language and toolchain for maintaining robust, optimal, and reusable software.
https://ziglang.org
MIT License
34.82k stars 2.55k forks source link

package manager: allow one dependency to be fulfilled by one of many alternatives #10516

Open kristoff-it opened 2 years ago

kristoff-it commented 2 years ago

Normally when a package has dependencies, all of them need to be provided for it to build successfully.

This proposal is about adding a mechanism that would allow to specify a dependency that can be satisfied by any package in a list of alternatives. The package manager at this point would be able to choose which element to provide based on a set of internal rules.

Since we haven't chosen yet a text format for enumerating dependencies, I'll use everyone's favorite to provide a concrete example. The syntax is not meant to be well designed, just focus on the semantics of the example.

tcp-client:
   version: 1
   deps: 
      - iguanaTLS@v2.2

http-client:
   version: 1
   deps: 
      - http-parser@v1
      - ssl: oneOf:
          - iguanaTLS@v2
          - libressl@v2
          - bearssl@v2
elazig-search:
   deps: 
      - bearssl@v2
      - http-client@v1
monzigdb:
   deps: 
      - tcp-client@v1
      - http-client@v1

So in this example you can see that http-client can use any of the mentioned tls libraries and how that can be useful to reduce the total number of dependencies when used by elazig-search and monzigdb.

More in general this feature could help the creation of "interface packages": packages whose only job is to extract a common interface from a set of concrete implementations for consumers that really value avoiding getting locked into a specific dependency. I think more could be said about the value of this practice but it's a bit outside of the scope of this proposal.

Not covered here but also necessary, is the ability to orchestrate the different optional dependencies in the Zig code (eg how can I add a conditional that depends on which dependency was fulfilled?).

daurnimator commented 2 years ago

Counter proposal:

nektro commented 2 years ago

I think the places where using this feature would help are very slim, and the places where maintainers would actually use it are even slimmer given the exponentially added complexity this adds to things like bug reports, building, etc.

I do not believe supporting this would be worth the effort on the core team.

nektro commented 2 years ago

its easy to look an an ecosystem and see there's 4 ssl libraries or 8 json parsers but they likely all have different constraints and APIs, so the flexibility in using one or the other in a dependency tree is near 0 even in the ideal case.

kristoff-it commented 2 years ago

its easy to look an an ecosystem and see there's 4 ssl libraries or 8 json parsers but they likely all have different constraints and APIs, so the flexibility in using one or the other in a dependency tree is near 0 even in the ideal case.

On the flip-side there are plenty of big projects that over time have accumulated N copies of redundant dependencies.

Java is a great example of that both for the redundancy (giant projects with like 5 different logging libraries used by different transitive dependencies), and also a great example of a situation where you really want to be able to swap implementations (log4j).

Ruby has https://github.com/intridea/multi_json

Rust has https://docs.rs/http-types/latest/http_types/

Python has plenty of WSGI web servers and apps and similar interfaces exist in Node and Ruby.

I'm sure there are more examples of ecosystems trying to come up with common interfaces for things.

Lastly, it's true that, if there are multiple implementations, then those will try to solve different variations of the same problem, but that doesn't immediately negate the fact that you could find a "minimum common denominator" interface among most of them that can be good enough for 80% of the use cases.

nektro commented 2 years ago

I think a better approach to this problem would be to have tree analysis tools than could let the developer know of candidates for these "potential redundancies" so that people could go to these projects and try and migrate them towards using the "community standard".

nektro commented 2 years ago

the only situation where a project would be entirely swappable would likely be a fork of the project they're already using. which switching to can be solved numerous other ways. Zigmod achieves this though an ID system that was picked up from # 943.

gereeter commented 2 years ago

Another important use-case for something like this is switching between a mainstream library and an alternate (usually slower and simpler) implementation with a more permissive license; in this case, the projects are very deliberately drop-in replacements of each other, and the motivation for the duplication is legal necessity. For example, Haskell's ghc-bignum is used to implement the ubiquitous Integer type and defaults to a backend based on GMP, but since GMP is under LGPL, it is sometimes necessary to use the native-Haskell backend, which is under BSD3.