Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Parameterization: OS/Arch/build tags #291

Closed
@sdboyer

Description

@sdboyer

To this point, dep has completely sidestepped the question of build tags. This is a big thing we need to deal with, and may affect the structure of lock and manifest files.

The basic issue: whereas the toolchain today operates within a concrete build environment (for any given run, there is one GOOS, one GOARCH, and a finite set of applied build tags), dep produces more broadly useful results when it computes not just the current environment, but across potential build environments - ideally, across all of them. In essence, the goal is that even if you're running dep on darwin/amd64, the lock file it produces should have sufficient information to be able to construct a vendor tree for linux/386, or freebsd/sparc64, or whatever (assuming they're any different).

Compare these examples - first, a lock.json now indicating three subpackages of a project are used:

        {
            "name": "golang.org/x/sys",
            "branch": "master",
            "revision": "e48874b42435b4347fc52bdee0424a52abc974d7",
            "packages": ["unix"]
        }

And one where the requirement for those subpackages is parameterized:

        {
            "name": "golang.org/x/sys",
            "branch": "master",
            "revision": "e48874b42435b4347fc52bdee0424a52abc974d7",
            "parameterized-packages": [
                {
                    "os": "solaris",
                    "packages": ["unix"]
                }
            ]
        }

With this additional information, it's immediately evident that the source code in golang.org/x/sys/unix - a rather large repository - isn't needed unless we need to build for solaris. Without this information, the tool would have to redo static analysis of the code in order to figure it out, which is just wasteful. Also, note that this example is not only real, but common; it results from relying on the very popular github.com/sirupsen/logrus - project.

Taking this approach means cross-compiling is possible by default. That's already something the go toolchain aims for, which strongly suggests that we're on the right track, and dep's strong default behavior should be to create portable lock files.

Now, if you/your project isn't cross-compiling or testing different os/arch combinations itself, then lock parameterization might seem a bit misleading - how do we know a lock's solution works on a different concrete build environment? Well, we don't, of course, but that's the wrong way to think about it; we don't know that a different os/arch would work today, either, and if a user on a different os/arch has a build that doesn't work, it's still strictly better if that build is reproducible than not.


Achieving lock parameterization first requires that gps start supporting a notion of it in the first place. There's a solid chunk of work to do on this:

  • The solver has to keep track of whether a given package is globally included, or only in a certain parameterized context - Keep tags on selected deps so we know the context of their inclusion sdboyer/gps#44
  • The parser in gps.ListPackages() currently lumps all imports together in the returned PackageTree's PackageOrErrs, regardless of build tag context. It needs to be refactored to return a parameterized view of a given directory's go code (no issue created yet)
  • Following on the preceding, PackageTree.ToReachMap() also needs to parameterize its returned information (no issue created yet)
  • "A parameterized view" sounds nice, but it could actually be tricky to create a concise representation of a directory when accounting for negated build tags (e.g. // +build !debug, because negative-matching against a non-finite set (build tags) is nasty. We may just have to preserve such negations directly in the lock.

Once the basic support for this is in place, we can also think about the ways that project authors can indicate that they want to ignore a particular os/arch/build tag set, or (an even stronger statement) that they do not work with a certain tag set.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions