-
Notifications
You must be signed in to change notification settings - Fork 232
pubspec: Add bin_dependencies or global_dependencies #1231
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
Comments
<img src="https://avatars.githubusercontent.com/u/4865287?v=3" align="left" width="48" height="48"hspace="10"> Comment by lrhn |
<img src="https://avatars.githubusercontent.com/u/188?v=3" align="left" width="48" height="48"hspace="10"> Comment by nex3 When we were first designing the package system, we intentionally decided to limit the number of different ways a dependency could be declared to encourage both conceptual clarity and straightforward implementation. I think that principle applies here: there isn't enough benefit from not having some dependencies downloaded under some circumstances to justify the complexity cost. Added NotPlanned label. |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan Example of why this would be useful: |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan Version lock is probably the bigger concern here, not downloading extra dependencies. This bit me again, causing me to have to put my executable and library in separate packages: http://github.com/seaneagan/den And it just came up again here: |
<img src="https://avatars.githubusercontent.com/u/1081711?v=3" align="left" width="48" height="48"hspace="10"> Comment by jmesserly cc @munificent. |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan I think this would get much easier to implement once we have the package spec: https://github.com/lrhn/dep-pkgspec Then all the deps can still be downloaded into the same place, but |
<img src="https://avatars.githubusercontent.com/u/46275?v=3" align="left" width="48" height="48"hspace="10"> Comment by munificent I'm going to re-open this because I'm increasingly hearing this is a problem and I don't want people to solve it by splitting their packages into pure lib / command line halves. Totally agree that package-spec will help here. Added Triaged label. |
<img src="https://avatars.githubusercontent.com/u/67586?v=3" align="left" width="48" height="48"hspace="10"> Comment by pq Yes please! This is something we're tangling significantly with in analyzer-land. |
<img src="https://avatars.githubusercontent.com/u/188?v=3" align="left" width="48" height="48"hspace="10"> Comment by nex3 A package's executables are part of its public API; it's valid for one package to depend on another because it wants to run that dependency's executable. If that executable's dependencies are distinct from its normal dependencies, that use-case breaks. This is analogous to a package exposing two classes, one of which has a dependency that the other does not. If a downstream package only uses one class, sure, it would be nice for it not to use the other class's dependency, but that's not how our dependency system works, and for good reason: if every package has to spell out exactly which dependencies are used by which pieces of its API, and which pieces of the APIs of its dependencies it uses, the whole system becomes untenably complex. And just like the multiple-classes case, if the dependencies or versioning story of two pieces of an API are different enough that they're causing problems, I don't think there's anything wrong with splitting them apart. We're planning on doing this with unittest, for example: there will be one "frontend" package for defining tests and a separate "backend" package for manipulating the infrastructure behind the definition, separated out so they can be versioned separately. |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan
A package shouldn't depend on a package solely for its executable, that's what
I think "breaks" is too strong. As mentioned in the original post, yes, it's harder for
I don't think anyone has or would suggest such a complex partitioning of dependencies. A better analogy is with dev_dependencies. Those are useful because for example packages want to co-locate their tests, build scripts, etc. with their public API, using the standard pub package layout conventions (/lib, /test, /tool), but they don't want dependers to inherit e.g. unittest, grinder, etc. dependencies. Similarly, packages want to co-locate one cohesive public API including an executable and a dart API, using the standard pub package layout conventions (/lib, /bin) without having dependers inherit e.g. args, prompt, and ansicolor.
That sounds like a good solution, but to a problem that's specific to the unittest package. Exposing executables however is a problem shared by a large percentage of packages. It's already partly solved by the /bin convention, |
<img src="https://avatars.githubusercontent.com/u/46275?v=3" align="left" width="48" height="48"hspace="10"> Comment by munificent
Not true. It's helpful to depend on packages that you only use executables from because it ensures everyone hacking on your package can easily run the right version of those executables. You can just tell people:
However, I'm not opposed to something like bin_dependencies, though it can be a tricky to implement correctly. |
<img src="https://avatars.githubusercontent.com/u/188?v=3" align="left" width="48" height="48"hspace="10"> Comment by nex3
This is incorrect. "pub global activate" is for end-users to install executables onto their systems for their direct use. If one package needs to use another's executable, it absolutely should depend on that package; making its users run "pub global activate" is an annoyingly manual installation step that interferes with the user's system state and doesn't respect version constraints. I want to emphasize again that we consider a package's executables to be part of its API, and this model is not likely to change. Even if we do decide to add some notion of bin dependencies, it will be in a way that preserves works with this model, rather than against it.
How would this help? The bin-inclusive package graph would be identical to package graphs today, and if it experiences version lock, installation would still fail. |
<img src="https://avatars.githubusercontent.com/u/405837?v=3" align="left" width="48" height="48"hspace="10"> Comment by zoechi I'm fighting a lot with package dependencies lately and every single dependency adds more headaches. Here its with examples https://bitbucket.org/andersmholmgren/shelf_auth/issue/6/please-make-it-compatible-with-shelf-060 (see end of the discussion) |
<img src="https://avatars.githubusercontent.com/u/46275?v=3" align="left" width="48" height="48"hspace="10"> Comment by munificent
This is exactly what dev_dependencies do, except that bin shouldn't be in that list. But for things in test, example, and tool, by all means do use dev_dependencies for those. |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan
I agree that that's a nice to have, but if folks are experiencing version lock they won't even get past the install, and thus won't be able to run the executables at all. This is not a problem with Instead of trying to jam in the dependencies of all the binaries of all your transitive dependencies into a single dependency graph, similar to
We add a step between 2. and 3., which is to run a new command: pub activate some_dep This is just like: pub global activate some_dep <some version or path or git repo> except that you never need to specify <some version or path or git repo> since that is already done for you by the pubspec. It only uses the dependencies of If there is desire to easily activate all the binaries of one's immediate dependencies that could just be a The lock files of the Then when
I personally like 2. a lot. And What do you all think? |
<img src="https://avatars.githubusercontent.com/u/1081711?v=3" align="left" width="48" height="48"hspace="10"> Comment by jmesserly fyi, proposal doc: https://docs.google.com/document/d/1lvbzyivCejhTuHLG4WI3YVThbQqJhPUrwajwTC-sXWU/edit looks great to me |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan Another example: |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="48" height="48"hspace="10"> Comment by seaneagan Another package:args conflict in issue dart-lang/sdk#23349. |
This would be very useful for the The package basically consists of a library that reads/writes a dump-info file and a set of binaries that does useful analyses on the dump-info file. This package is bundled with the SDK since dart2js uses it, but dart2js only uses the 'library' aspect of it. I added a dependency in one of the binaries and now have to add that dependency to the SDK, even though the SDK will never use a binary in dart2js_info. Since we have package specs now, isn't it not really true that a library's binaries are part of it's public API? |
That doesn't really affect it one way or another. |
Oops! I just specced out another proposal at dart-lang/sdk#34837, which allows each executable to specify its own specs. As for the idea that an entire package's contents are part of its public API, yeah that's tricky. Technically, today, a dependant could even reach out and load a test file, or read a file in |
Note that you can't access anything outside of Sure you can put an absolute uri import to a non-lib dir in your pubcache but that does not need to continue to work imo. |
I'm curious about whether we can specify "public API" a little more tightly. Here's our current text on Public tools in package layout:
However, as @jakemac53 writes above, "you can't access anything outside of lib with a package: uri", so... what we're really saying here is that the developers of a downstream package, which depends on your package, can run scripts from your package's I think this means we could lay out an "executable dependencies" API (like mine 😄 dart-lang/sdk#34837), wherein pub should fetch all executable dependencies for each dev_dependency, so that a developer could run tools like grinder, test, etc. One wrench in this plan would be packages like mockito, which both depends on test for its API (it imports |
We sometimes hit version lock due to incompatible transitive dependencies, and a good portion of the time it's due to packages that declare executables. Some packages like Here's another idea, similar to @seanegan's proposal above that would solve parts of my problem as well as parts of the problem discussed above. It also maintains that a package's executables are part of its API, and keeps them as
Example: # pubspec.yaml
dev_executable_dependencies:
a: ^1.1.1
b: ^2.2.2 # pubspec_executables.lock
executables:
a:
version: "1.0.0"
packages:
c:
version: "1.0.0" # incompatible with package b's constraints, but that's
# okay since the dependency graphs are isolated
d:
version: "4.1.0"
b:
version: "1.0.0"
packages:
c:
version: "2.0.0" # incompatible with package a's constraints, but that's
# okay since the dependency graphs are isolated
d:
version: "4.2.0" There are some flaws with this approach, though. This won't help for packages that expose both Dart APIs and executables. We would have to rely on those maintainers splitting out their APIs and executables into separate packages. It might be difficult in practice to ensure compatibility between split up API/executable packages whose behavior is dependent on a transitive dependency. Say, for the example above, we want to ensure Also, having a separate lockfile wouldn't be ideal. Anyways, I was hoping that sharing an idea for a different approach to this problem might spark some better ideas 😄. |
@jonasfj has an alternative proposal called "private dependencies" that should cover this use case as well. Could you open an issue with a rough description, and close this one in favour of the other? |
<img src="https://avatars.githubusercontent.com/u/444270?v=3" align="left" width="96" height="96"hspace="10"> Issue by seaneagan
Originally opened as dart-lang/sdk#22054
Many packages expose command-line apps as well as dart APIs to that same functionality. Often the command-line apps require additional dependencies such as
args
,unscripted
,ansicolor
,prompt
, etc. Similar to how dev_dependencies allow you to specify dependencies only needed by package developers, bin_dependencies could allow specifying dependencies only needed by folks running command-line apps from the package.For
pub global activate
/pub global run
it would be easy, because those use a self-contained dependency graph.But for
pub run
, it would require separating the dependencies into two separate graphs, e.g.packages
/pubspec.lock
andbin_packages
/pubspec_bin.lock
.The text was updated successfully, but these errors were encountered: