| # Proposal: Binary-Only Packages |
| |
| Author: Russ Cox |
| |
| Last updated: April 24, 2016 |
| |
| Discussion at [golang.org/issue/2775](https://golang.org/issue/2775). |
| |
| ## Abstract |
| |
| We propose a way to incorporate binary-only packages (without complete source code) into a cmd/go workspace. |
| |
| ## Background |
| |
| It is common in C for a code author to provide a C header file and the compiled form of a library |
| but not the complete source code. |
| The go command has never supported this officially. |
| |
| |
| In very early versions of Go, it was possible to arrange for a binary-only package simply by |
| removing the source code after compiling. |
| But that state looks the same as when the package source code has been deleted |
| because the package itself is no longer available, in which case the compiled form |
| should not continue to be used. |
| For the past many years the Go command has assumed the latter. |
| |
| Then it was possible to arrange for a binary-only package by replacing the source code |
| after compiling, while keeping the modification time of the source code older than |
| the modification time of the compiled form. |
| But in normal usage, removing an individual source file is cause for recompilation |
| even though that cannot be seen in the modification times. |
| To detect that situation, |
| Go 1.5 started using the full set of source file names that went into |
| a package as one input to a hash that produced the package's ``build ID''. |
| If the go command's expected build ID does not match the compiled package's |
| build ID, the compiled package is out of date, even if the modification times suggest |
| otherwise (see [golang.org/cl/9154](https://golang.org/cl/9154)). |
| |
| From Go 1.5 then, to arrange for a binary-only package, |
| it has been necessary to replace the source code after compiling |
| but keep the same set of file names and also keep the source |
| modification times older than the compiled package's. |
| |
| In the future we may experiment with including the source code itself |
| in the hash that produces the build ID, which would completely |
| defeat any attempt at binary-only packages. |
| |
| Fundamentally, as time goes on the go command gets better and better at detecting |
| mismatches between the source code and the compiled form, |
| yet in some cases it is explicitly desired that the source code not match |
| the compiled form (specifically, that the source code not be included at all). |
| If this usage is to keep working, it must be explicitly supported. |
| |
| ## Proposal |
| |
| We propose to add official support for binary-only packages to the cmd/go toolchain, |
| by introduction of a new `//go:binary-only-package` comment. |
| |
| The go/build package's type Package will contain a new field `IncompleteSources bool` indicating |
| whether the `//go:binary-only-package` comment is present. |
| |
| The go command will refuse to recompile a package containing the comment. |
| If a suitable binary form of the package is already installed, the go command will use it. |
| Otherwise the go command will report that the binary form is missing and cannot be built. |
| |
| Users must install the package binary into the correct location in the $GOPATH/pkg tree |
| themselves. Distributors of binary-only packages might distribute |
| them as .zip files to be unpacked in the root of a $GOPATH, including files in both the src/ and pkg/ |
| tree. |
| |
| The “go get” command will still require complete source code and will not |
| recognize or otherwise enable the distribution of binary-only packages. |
| |
| ## Rationale |
| |
| Various users have reported working with companies that want to provide them with |
| binary but not source forms of purchased packages. |
| We want to define an explicit way to do that instead of fielding bug reports |
| each time the go command gets smarter about detecting source-vs-binary mismatches. |
| |
| The package source code itself must be present in some form, |
| or else we can't tell if the package was deleted entirely (see background above). |
| The implication is that it will simply not be the actual source code for the package. |
| A special comment is a natural way to signal this situation, |
| especially since the go command is already reading the source code |
| for package name, import information, and build tag comments. |
| Having a “fake” version of the source code also provides a way to supply |
| documentation compatible with “go doc” and “godoc” |
| even though the complete source code is missing. |
| |
| The compiled form of the package does contain information about the source code, |
| for example source file names, type definitions for data structures used in the |
| public API, and inlined function bodies. It is assumed that the distributors of |
| binary-only packages understand that they include this information. |
| |
| ## Compatibility |
| |
| There are no problems raised by the |
| [compatibility guidelines](https://golang.org/doc/go1compat). |
| If anything, the explicit support will help keep such binary-only packages |
| working better than they have in the past. |
| |
| To the extent that tools process source code and not compiled packages, |
| those tools will not work with binary-only packages. |
| The compiler and linker will continue to enforce that all packages be compiled |
| with the same version of the toolchain: a binary-only package built with Go 1.4 |
| will not work with Go 1.5. |
| Authors and users of binary-only packages must live with these implications. |
| |
| ## Implementation |
| |
| The implementation is essentially as described in the proposal section above. |
| |
| One additional detail is that the go command must load the build ID for the package |
| in question from the compiled binary form directly, instead of deriving it from the |
| source files. |
| |
| I will implement this change for Go 1.7. |