LoopPerfect / buckaroo

The decentralized package manager for C++ and friends 🏝️
https://buckaroo.pm
MIT License
933 stars 33 forks source link

Dependency groups #244

Open njlr opened 5 years ago

njlr commented 5 years ago

The goal of this feature is to make it easier for users to extract dependencies for a particular usage or platform.

Inside the manifest, we should allow the user to tag dependencies as belonging to particular groups.

It might look like this:

[[dependency]]
package = "github.com/abc/def"
version = "*"
groups = [ "dev" ]

[[dependency]]
package = "github.com/abc/ijk"
version = "*"
groups = [ "macos" ]

[[dependency]]
package = "github.com/abc/lmno"
version = "*"
groups = [ "dev", "linux" ]

By default, a dependency would not belong to any groups.

We would then provide a macro in buckaroo_macros.bzl that allows the user to extract all dependencies for a given group:

load('//:buckaroo_macros.bzl', 'buckaroo_deps_from_group')

cxx_binary(
  name = 'app', 
  srcs = [
    'main.cpp', 
  ],
  platform_deps = [
    ('macos.*', buckaroo_deps_from_group('macos')),
  ], 
)

Open questions:

This is how we should support development and platform dependencies.

njlr commented 5 years ago

Once we have tags on dependencies, the behaviour of buckaroo_deps() should change to return all deps that do not have any tags.

We would introduce a new function for returning all deps for any tag buckaroo_all_deps() (name TBD)

iwatakeshi commented 5 years ago

Hi. This is just a thought, but I think it would be better to introduce a boolean to determine whether the dependency is for development. Also, instead of groups, you could introduce an array for the operating systems such as os. The result would look like this:

[[dependency]]
package = "github.com/abc/def"
version = "*"
dev = true 

[[dependency]]
package = "github.com/abc/ijk"
version = "*"
os = [ "macos" ]

[[dependency]]
package = "github.com/abc/lmno"
version = "*"
os = [ "linux" ]
njlr commented 5 years ago

Hi @iwatakeshi, thanks for the response!

Our initial idea was exactly as you describe, with os and dev as built-in concepts. We came up with two issues with this approach.

1. What do the macros look like when the user extracts the dependency?

With the "groups" approach, it looks like this:

macos_deps = buckaroo_deps_group([ 'macos' ])
macos_dev_deps = buckaroo_deps_group([ 'macos', 'dev' ])

But with the "os + dev" approach it (might) look like this:

macos_deps = buckaroo_deps_os('macos')
macos_dev_deps = buckaroo_deps_os_dev('macos') # Feels wrong!

I think the first way looks nicer. What do you think?

2. How do we support other kinds of group?

There might be more types of dependency, not just platform-specific or development-specific.

With the "groups" approach, the user can just define a new group:

[[dependency]]
package = "github.com/abc/lmno"
version = "*"
groups = [ "custom" ]

and use it like this:

custom_deps = buckaroo_deps_group([ 'custom' ])

I'm not sure how this could work with the "os + dev" approach. Any ideas?

None of this is implemented yet, so we would appreciate your thoughts!

iwatakeshi commented 5 years ago

@njlr Ah. I see what you're saying. Would something like the following be possible?

macos_deps = buckaroo_deps(['macos']) # defaults to False
macos_dev_deps = buckaroo_deps(['macos'], dev=True)

# or maybe filtering out the deps?
macos_deps = buckaroo_deps(['macos']) # defaults to False
macos_dev_deps = filter(macos_deps) # where filter() is a magical filtering function
njlr commented 5 years ago

Given that the build scripts are written in Python (well, a Python variant called Skylark), a filter function is definitely possible. We can also have named arguments as you suggest (dev = True).

I think this could work well.

However, this leaves the question of custom groups. I think that this feature is very important, because we cannot anticipate all of the kinds of dependency that people might have.

We could also consider doing both! I'm not sure if the complexity will be worth it though.

iwatakeshi commented 5 years ago

It could also have another keyword-parameter groups so the signature would look something like:

buckaroo_deps(groups=[], os=[], dev=False); # where groups and os can be a string, '*'

A naive approach would be to just filter out the array by dev then groups, then os.

But, like you said, it might get complicated. 🤷‍♂️