mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] all: merge branch 'master' into dev.link
Bring in Than's fix of #35779. The only merge conflict is cmd/link/internal/loadelf/ldelf.go, with a modification-deletion conflict. Change-Id: Id2fcfd2094a31120966a6ea9c462b4ec76646b10
This commit is contained in:
commit
f7672d39ca
200 changed files with 3558 additions and 2028 deletions
|
|
@ -171,6 +171,16 @@ TODO
|
|||
TODO
|
||||
</p>
|
||||
|
||||
<p><!-- CL 171844 and many others -->
|
||||
Internal timers, used by
|
||||
<a href="/pkg/time/#After"><code>time.After</code></a>,
|
||||
<a href="/pkg/time/#Tick"><code>time.Tick</code></a>,
|
||||
<a href="/pkg/net/#Conn"><code>net.Conn.SetDeadline</code></a>,
|
||||
and friends, are more efficient, with less lock contention and fewer
|
||||
context switches.
|
||||
This is a performance improvement that should not cause any user
|
||||
visible changes.
|
||||
</p>
|
||||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
|
|
|
|||
514
doc/modules.md
514
doc/modules.md
|
|
@ -5,57 +5,551 @@
|
|||
}-->
|
||||
<!-- TODO(jayconrod): ensure golang.org/x/website can render Markdown or convert
|
||||
this document to HTML before Go 1.14. -->
|
||||
<!-- TODO(jayconrod): ensure Markdown renderer adds anchors or add them
|
||||
manually. -->
|
||||
<!-- TODO(jayconrod): ensure anchors work correctly after Markdown rendering -->
|
||||
|
||||
<a id="introduction"></a>
|
||||
## Introduction
|
||||
|
||||
## Glossary
|
||||
<a id="modules-overview"></a>
|
||||
## Modules, packages, and versions
|
||||
|
||||
## Packages, modules, and versions
|
||||
A [*module*](#glos-module) is a collection of packages that are released,
|
||||
versioned, and distributed together. A module is identified by a [*module
|
||||
path*](#glos-module-path), which is declared in a [`go.mod`
|
||||
file](#go.mod-files), together with information about the module's
|
||||
dependencies. The [*module root directory*](#glos-module-root-directory) is the
|
||||
directory that contains the `go.mod` file. The [*main
|
||||
module*](#glos-main-module) is the module containing the directory where the
|
||||
`go` command is invoked.
|
||||
|
||||
## go.mod files
|
||||
Each [*package*](#glos-package) within a module is a collection of source files
|
||||
in the same directory that are compiled together. A [*package
|
||||
path*](#glos-package-path) is the module path joined with the subdirectory
|
||||
containing the package (relative to the module root). For example, the module
|
||||
`"golang.org/x/net"` contains a package in the directory `"html"`. That
|
||||
package's path is `"golang.org/x/net/html"`.
|
||||
|
||||
### go.mod file format
|
||||
<a id="versions"></a>
|
||||
### Versions
|
||||
|
||||
A [*version*](#glos-version) identifies an immutable snapshot of a module, which
|
||||
may be either a [release](#glos-release-version) or a
|
||||
[pre-release](#glos-pre-release-version). Each version starts with the letter
|
||||
`v`, followed by a semantic version. See [Semantic Versioning
|
||||
2.0.0](https://semver.org/spec/v2.0.0.html) for details on how versions are
|
||||
formatted, interpreted, and compared.
|
||||
|
||||
To summarize, a semantic version consists of three non-negative integers (the
|
||||
major, minor, and patch versions, from left to right) separated by dots. The
|
||||
patch version may be followed by an optional pre-release string starting with a
|
||||
hyphen. The pre-release string or patch version may be followed by a build
|
||||
metadata string starting with a plus. For example, `v0.0.0`, `v1.12.134`,
|
||||
`v8.0.5-pre`, and `v2.0.9+meta` are valid versions.
|
||||
|
||||
Each part of a version indicates whether the version is stable and whether it is
|
||||
compatible with previous versions.
|
||||
|
||||
* The [major version](#glos-major-version) must be incremented and the minor
|
||||
and patch versions must be set to zero after a backwards incompatible change
|
||||
is made to the module's public interface or documented functionality, for
|
||||
example, after a package is removed.
|
||||
* The [minor version](#glos-minor-version) must be incremented and the patch
|
||||
version set to zero after a backwards compatible change, for example, after a
|
||||
new function is added.
|
||||
* The [patch version](#glos-patch-version) must be incremented after a change
|
||||
that does not affect the module's public interface, such as a bug fix or
|
||||
optimization.
|
||||
* The pre-release suffix indicates a version is a
|
||||
[pre-release](#glos-pre-release-version). Pre-release versions sort before
|
||||
the corresponding release versions. For example, `v1.2.3-pre` comes before
|
||||
`v1.2.3`.
|
||||
* The build metadata suffix is ignored for the purpose of comparing versions.
|
||||
Tags with build metadata are ignored in version control repositories, but
|
||||
build metadata is preserved in versions specified in `go.mod` files. The
|
||||
suffix `+incompatible` denotes a version released before migrating to modules
|
||||
version major version 2 or later (see [Compatibility with non-module
|
||||
repositories](#non-module-compat).
|
||||
|
||||
A version is considered unstable if its major version is 0 or it has a
|
||||
pre-release suffix. Unstable versions are not subject to compatibility
|
||||
requirements. For example, `v0.2.0` may not be compatible with `v0.1.0`, and
|
||||
`v1.5.0-beta` may not be compatible with `v1.5.0`.
|
||||
|
||||
Go may access modules in version control systems using tags, branches, or
|
||||
revisions that don't follow these conventions. However, within the main module,
|
||||
the `go` command will automatically convert revision names that don't follow
|
||||
this standard into canonical versions. The `go` command will also remove build
|
||||
metadata suffixes (except for `+incompatible`) as part of this process. This may
|
||||
result in a [*pseudo-version*](#glos-pseudo-version), a pre-release version that
|
||||
encodes a revision identifier (such as a Git commit hash) and a timestamp from a
|
||||
version control system. For example, the command `go get -d
|
||||
golang.org/x/net@daa7c041` will convert the commit hash `daa7c041` into the
|
||||
pseudo-version `v0.0.0-20191109021931-daa7c04131f5`. Canonical versions are
|
||||
required outside the main module, and the `go` command will report an error if a
|
||||
non-canonical version like `master` appears in a `go.mod` file.
|
||||
|
||||
<a id="major-version-suffixes"></a>
|
||||
### Major version suffixes
|
||||
|
||||
Starting with major version 2, module paths must have a [*major version
|
||||
suffix*](#glos-major-version-suffix) like `/v2` that matches the major
|
||||
version. For example, if a module has the path `example.com/mod` at `v1.0.0`, it
|
||||
must have the path `example.com/mod/v2` at version `v2.0.0`.
|
||||
|
||||
Major version suffixes implement the [*import compatibility
|
||||
rule*](https://research.swtch.com/vgo-import):
|
||||
|
||||
> If an old package and a new package have the same import path,
|
||||
> the new package must be backwards compatible with the old package.
|
||||
|
||||
By definition, packages in a new major version of a module are not backwards
|
||||
compatible with the corresponding packages in the previous major version.
|
||||
Consequently, starting with `v2`, packages need new import paths. This is
|
||||
accomplished by adding a major version suffix to the module path. Since the
|
||||
module path is a prefix of the import path for each package within the module,
|
||||
adding the major version suffix to the module path provides a distinct import
|
||||
path for each incompatible version.
|
||||
|
||||
Major version suffixes are not allowed at major versions `v0` or `v1`. There is
|
||||
no need to change the module path between `v0` and `v1` because `v0` versions
|
||||
are unstable and have no compatibility guarantee. Additionally, for most
|
||||
modules, `v1` is backwards compatible with the last `v0` version; a `v1` version
|
||||
acts as a commitment to compatibility, rather than an indication of
|
||||
incompatible changes compared with `v0`.
|
||||
|
||||
As a special case, modules paths starting with `gopkg.in/` must always have a
|
||||
major version suffix, even at `v0` and `v1`. The suffix must start with a dot
|
||||
rather than a slash (for example, `gopkg.in/yaml.v2`).
|
||||
|
||||
Major version suffixes let multiple major versions of a module coexist in the
|
||||
same build. This may be necessary due to a [diamond dependency
|
||||
problem](https://research.swtch.com/vgo-import#dependency_story). Ordinarily, if
|
||||
a module is required at two different versions by transitive dependencies, the
|
||||
higher version will be used. However, if the two versions are incompatible,
|
||||
neither version will satisfy all clients. Since incompatible versions must have
|
||||
different major version numbers, they must also have different module paths due
|
||||
to major version suffixes. This resolves the conflict: modules with distinct
|
||||
suffixes are treated as separate modules, and their packages—even packages in
|
||||
same subdirectory relative to their module roots—are distinct.
|
||||
|
||||
Many Go projects released versions at `v2` or higher without using a major
|
||||
version suffix before migrating to modules (perhaps before modules were even
|
||||
introduced). These versions are annotated with a `+incompatible` build tag (for
|
||||
example, `v2.0.0+incompatible`). See [Compatibility with non-module
|
||||
repositories](#compatibility-with-non-module-repositories) for more information.
|
||||
|
||||
<a id="resolve-pkg-mod"></a>
|
||||
### Resolving a package to a module
|
||||
|
||||
When the `go` command loads a package using a [package
|
||||
path](#glos-package-path), it needs to determine which module provides the
|
||||
package.
|
||||
|
||||
The `go` command starts by searching the [build list](#glos-build-list) for
|
||||
modules with paths that are prefixes of the package path. For example, if the
|
||||
package `example.com/a/b` is imported, and the module `example.com/a` is in the
|
||||
build list, the `go` command will check whether `example.com/a` contains the
|
||||
package, in the directory `b`. At least one file with the `.go` extension must
|
||||
be present in a directory for it to be considered a package. [Build
|
||||
constraints](/pkg/go/build/#hdr-Build_Constraints) are not applied for this
|
||||
purpose. If exactly one module in the build list provides the package, that
|
||||
module is used. If two or more modules provide the package, an error is
|
||||
reported. If no modules provide the package, the `go` command will attempt to
|
||||
find a new module (unless the flags `-mod=readonly` or `-mod=vendor` are used,
|
||||
in which case, an error is reported).
|
||||
|
||||
<!-- NOTE(golang.org/issue/27899): the go command reports an error when two
|
||||
or more modules provide a package with the same path as above. In the future,
|
||||
we may try to upgrade one (or all) of the colliding modules.
|
||||
-->
|
||||
|
||||
When the `go` command looks up a new module for a package path, it checks the
|
||||
`GOPROXY` environment variable, which is a comma-separated list of proxy URLs or
|
||||
the keywords `direct` or `off`. A proxy URL indicates the `go` command should
|
||||
contact a [module proxy](#glos-module-proxy) using the [`GOPROXY`
|
||||
protocol](#goproxy-protocol). `direct` indicates that the `go` command should
|
||||
[communicate with a version control system](#communicating-with-vcs). `off`
|
||||
indicates that no communication should be attempted. The `GOPRIVATE` and
|
||||
`GONOPROXY` [environment variables](#environment-variables) can also be used to
|
||||
control this behavior.
|
||||
|
||||
For each entry in the `GOPROXY` list, the `go` command requests the latest
|
||||
version of each module path that might provide the package (that is, each prefix
|
||||
of the package path). For each successfully requested module path, the `go`
|
||||
command will download the module at the latest version and check whether the
|
||||
module contains the requested package. If one or more modules contain the
|
||||
requested package, the module with the longest path is used. If one or more
|
||||
modules are found but none contain the requested package, an error is
|
||||
reported. If no modules are found, the `go` command tries the next entry in the
|
||||
`GOPROXY` list. If no entries are left, an error is reported.
|
||||
|
||||
For example, suppose the `go` command is looking for a module that provides the
|
||||
package `golang.org/x/net/html`, and `GOPROXY` is set to
|
||||
`https://corp.example.com,https://proxy.golang.org`. The `go` command may make
|
||||
the following requests:
|
||||
|
||||
* To `https://corp.example.com/` (in parallel):
|
||||
* Request for latest version of `golang.org/x/net/html`
|
||||
* Request for latest version of `golang.org/x/net`
|
||||
* Request for latest version of `golang.org/x`
|
||||
* Request for latest version of `golang.org`
|
||||
* To `https://proxy.golang.org/`, if all requests to `https://corp.example.com/`
|
||||
have failed with 404 or 410:
|
||||
* Request for latest version of `golang.org/x/net/html`
|
||||
* Request for latest version of `golang.org/x/net`
|
||||
* Request for latest version of `golang.org/x`
|
||||
* Request for latest version of `golang.org`
|
||||
|
||||
After a suitable module has been found, the `go` command will add a new
|
||||
requirement with the new module's path and version to the main module's `go.mod`
|
||||
file. This ensures that when the same package is loaded in the future, the same
|
||||
module will be used at the same version. If the resolved package is not imported
|
||||
by a package in the main module, the new requirement will have an `// indirect`
|
||||
comment.
|
||||
|
||||
<a id="go.mod-files"></a>
|
||||
## `go.mod` files
|
||||
|
||||
<a id="go.mod-file-format"></a>
|
||||
### `go.mod` file format
|
||||
|
||||
<a id="minimal-version-selection"></a>
|
||||
### Minimal version selection (MVS)
|
||||
|
||||
<a id="non-module-compat"></a>
|
||||
### Compatibility with non-module repositories
|
||||
|
||||
<a id="mod-commands"></a>
|
||||
## Module-aware build commands
|
||||
|
||||
<a id="enabling"></a>
|
||||
### Enabling modules
|
||||
|
||||
<a id="initializing"></a>
|
||||
### Initializing modules
|
||||
|
||||
<a id="build-commands"></a>
|
||||
### Build commands
|
||||
|
||||
<a id="vendoring"></a>
|
||||
### Vendoring
|
||||
|
||||
<a id="go-mod-download"></a>
|
||||
### `go mod download`
|
||||
|
||||
<a id="go-mod-verify"></a>
|
||||
### `go mod verify`
|
||||
|
||||
<a id="go-mod-edit"></a>
|
||||
### `go mod edit`
|
||||
|
||||
<a id="go-clean-modcache"></a>
|
||||
### `go clean -modcache`
|
||||
|
||||
<a id="commands-outside"></a>
|
||||
### Module commands outside a module
|
||||
|
||||
<a id="retrieving-modules"></a>
|
||||
## Retrieving modules
|
||||
|
||||
### GOPROXY protocol
|
||||
<a id="goproxy-protocol"></a>
|
||||
### `GOPROXY` protocol
|
||||
|
||||
### Module zip requirements
|
||||
A [*module proxy*](#glos-module-proxy) is an HTTP server that can respond to
|
||||
`GET` requests for paths specified below. The requests have no query parameters,
|
||||
and no specific headers are required, so even a site serving from a fixed file
|
||||
system (including a `file://` URL) can be a module proxy.
|
||||
|
||||
### Privacy
|
||||
Successful HTTP responses must have the status code 200 (OK). Redirects (3xx)
|
||||
are followed. Responses with status codes 4xx and 5xx are treated as errors.
|
||||
The error codes 404 (Not Found) and 410 (Gone) indicate that the
|
||||
requested module or version is not available on the proxy, but it may be found
|
||||
elsewhere. Error responses should have content type `text/plain` with
|
||||
`charset` either `utf-8` or `us-ascii`.
|
||||
|
||||
The `go` command may be configured to contact proxies or source control servers
|
||||
using the `GOPROXY` environment variable, which is a comma-separated list of
|
||||
URLs or the keywords `direct` or `off` (see [Environment
|
||||
variables](#environment-variables) for details). When the `go` command receives
|
||||
a 404 or 410 response from a proxy, it falls back to later proxies in the
|
||||
list. The `go` command does not fall back to later proxies in response to other
|
||||
4xx and 5xx errors. This allows a proxy to act as a gatekeeper, for example, by
|
||||
responding with error 403 (Forbidden) for modules not on an approved list.
|
||||
|
||||
The table below specifies queries that a module proxy must respond to. For each
|
||||
path, `$base` is the path portion of a proxy URL,`$module` is a module path, and
|
||||
`$version` is a version. For example, if the proxy URL is
|
||||
`https://example.com/mod`, and the client is requesting the `go.mod` file for
|
||||
the module `golang.org/x/text` at version `v0.3.2`, the client would send a
|
||||
`GET` request for `https://example.com/mod/golang.org/x/text/@v/v0.3.2.mod`.
|
||||
|
||||
To avoid ambiguity when serving from case-insensitive file systems,
|
||||
the `$module` and `$version` elements are case-encoded by replacing every
|
||||
uppercase letter with an exclamation mark followed by the corresponding
|
||||
lower-case letter. This allows modules `example.com/M` and `example.com/m` to
|
||||
both be stored on disk, since the former is encoded as `example.com/!m`.
|
||||
|
||||
<!-- TODO(jayconrod): This table has multi-line cells, and GitHub Flavored
|
||||
Markdown doesn't have syntax for that, so we use raw HTML. Gitiles doesn't
|
||||
include this table in the rendered HTML. Once x/website has a Markdown renderer,
|
||||
ensure this table is readable. If the cells are too large, and it's difficult
|
||||
to scan, use paragraphs or sections below.
|
||||
-->
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Path</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>$base/$module/@v/list</code></td>
|
||||
<td>
|
||||
Returns a list of known versions of the given module in plain text, one
|
||||
per line. This list should not include pseudo-versions.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>$base/$module/@v/$version.info</code></td>
|
||||
<td>
|
||||
<p>
|
||||
Returns JSON-formatted metadata about a specific version of a module.
|
||||
The response must be a JSON object that corresponds to the Go data
|
||||
structure below:
|
||||
</p>
|
||||
<pre>
|
||||
type Info struct {
|
||||
Version string // version string
|
||||
Time time.Time // commit time
|
||||
}
|
||||
</pre>
|
||||
<p>
|
||||
The <code>Version</code> field is required and must contain a valid,
|
||||
<a href="#glos-canonical-version">canonical version</a> (see
|
||||
<a href="#versions">Versions</a>). The <code>$version</code> in the
|
||||
request path does not need to be the same version or even a valid
|
||||
version; this endpoint may be used to find versions for branch names
|
||||
or revision identifiers. However, if <code>$version</code> is a
|
||||
canonical version with a major version compatible with
|
||||
<code>$module</code>, the <code>Version</code> field in a successful
|
||||
response must be the same.
|
||||
</p>
|
||||
<p>
|
||||
The <code>Time</code> field is optional. If present, it must be a
|
||||
string in RFC 3339 format. It indicates the time when the version
|
||||
was created.
|
||||
</p>
|
||||
<p>
|
||||
More fields may be added in the future, so other names are reserved.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>$base/$module/@v/$version.mod</code></td>
|
||||
<td>
|
||||
Returns the <code>go.mod</code> file for a specific version of a
|
||||
module. If the module does not have a <code>go.mod</code> file at the
|
||||
requested version, a file containing only a <code>module</code>
|
||||
statement with the requested module path must be returned. Otherwise,
|
||||
the original, unmodified <code>go.mod</code> file must be returned.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>$base/$module/@v/$version.zip</code></td>
|
||||
<td>
|
||||
Returns a zip file containing the contents of a specific version of
|
||||
a module. See <a href="#zip-format">Module zip format</a> for details
|
||||
on how this zip file must be formatted.
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>$base/$module/@latest</code></td>
|
||||
<td>
|
||||
Returns JSON-formatted metadata about the latest known version of a
|
||||
module in the same format as
|
||||
<code>$base/$module/@v/$version.info</code>. The latest version should
|
||||
be the version of the module that the <code>go</code> command should use
|
||||
if <code>$base/$module/@v/list</code> is empty or no listed version is
|
||||
suitable. This endpoint is optional, and module proxies are not required
|
||||
to implement it.
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
When resolving the latest version of a module, the `go` command will request
|
||||
`$base/$module/@v/list`, then, if no suitable versions are found,
|
||||
`$base/$module/@latest`. The `go` command prefers, in order: the semantically
|
||||
highest release version, the semantically highest pre-release version, and the
|
||||
chronologically most recent pseudo-version. In Go 1.12 and earlier, the `go`
|
||||
command considered pseudo-versions in `$base/$module/@v/list` to be pre-release
|
||||
versions, but this is no longer true since Go 1.13.
|
||||
|
||||
A module proxy must always serve the same content for successful
|
||||
responses for `$base/$module/$version.mod` and `$base/$module/$version.zip`
|
||||
queries. This content is [cryptographically authenticated](#authenticating)
|
||||
using [`go.sum` files](#go.sum-file-format) and, by default, the
|
||||
[checksum database](#checksum-database).
|
||||
|
||||
The `go` command caches most content it downloads from module proxies in its
|
||||
module cache in `$GOPATH/pkg/mod/cache/download`. Even when downloading directly
|
||||
from version control systems, the `go` command synthesizes explicit `info`,
|
||||
`mod`, and `zip` files and stores them in this directory, the same as if it had
|
||||
downloaded them directly from a proxy. The cache layout is the same as the proxy
|
||||
URL space, so serving `$GOPATH/pkg/mod/cache/download` at (or copying it to)
|
||||
`https://example.com/proxy` would let users access cached module versions by
|
||||
setting `GOPROXY` to `https://example.com/proxy`.
|
||||
|
||||
<a id="communicating-with-proxies"></a>
|
||||
### Communicating with proxies
|
||||
|
||||
<a id="communicating-with-vcs"></a>
|
||||
### Communicating with version control systems
|
||||
|
||||
<a id="custom-import-paths"></a>
|
||||
### Custom import paths
|
||||
|
||||
<!-- TODO(jayconrod): custom import paths, details of direct mode -->
|
||||
|
||||
<a id="path-constraints"></a>
|
||||
### File name and path constraints
|
||||
|
||||
<a id="zip-format"></a>
|
||||
### Module zip format
|
||||
|
||||
<a id="private-modules"></a>
|
||||
### Private modules
|
||||
|
||||
<a id="authenticating"></a>
|
||||
## Authenticating modules
|
||||
|
||||
<a id="go.sum-file-format"></a>
|
||||
### go.sum file format
|
||||
|
||||
<a id="checksum-database"></a>
|
||||
### Checksum database
|
||||
|
||||
### Privacy
|
||||
<a id="privacy"></a>
|
||||
## Privacy
|
||||
|
||||
<a id="environment-variables"></a>
|
||||
## Environment variables
|
||||
|
||||
<a id="glossary">
|
||||
## Glossary
|
||||
|
||||
<a id="glos-build-list"></a>
|
||||
**build list:** The list of module versions that will be used for a build
|
||||
command such as `go build`, `go list`, or `go test`. The build list is
|
||||
determined from the [main module's](#glos-main-module) [`go.mod`
|
||||
file](#glos-go.mod-file) and `go.mod` files in transitively required modules
|
||||
using [minimal version selection](#glos-minimal-version-selection). The build
|
||||
list contains versions for all modules in the [module
|
||||
graph](#glos-module-graph), not just those relevant to a specific command.
|
||||
|
||||
<a id="glos-canonical-version">
|
||||
**canonical version:** A correctly formatted [version](#glos-version) without
|
||||
a build metadata suffix other than `+incompatible`. For example, `v1.2.3`
|
||||
is a canonical version, but `v1.2.3+meta` is not.
|
||||
|
||||
<a id="glos-go.mod-file"></a>
|
||||
**`go.mod` file:** The file that defines a module's path, requirements, and
|
||||
other metadata. Appears in the [module's root
|
||||
directory](#glos-module-root-directory). See the section on [`go.mod`
|
||||
files](#go.mod-files).
|
||||
|
||||
<a id="glos-import-path"></a>
|
||||
**import path:** A string used to import a package in a Go source file.
|
||||
Synonymous with [package path](#glos-package-path).
|
||||
|
||||
<a id="glos-main-module"></a>
|
||||
**main module:** The module in which the `go` command is invoked.
|
||||
|
||||
<a id="glos-major-version"></a>
|
||||
**major version:** The first number in a semantic version (`1` in `v1.2.3`). In
|
||||
a release with incompatible changes, the major version must be incremented, and
|
||||
the minor and patch versions must be set to 0. Semantic versions with major
|
||||
version 0 are considered unstable.
|
||||
|
||||
<a id="glos-major-version-suffix"></a>
|
||||
**major version suffix:** A module path suffix that matches the major version
|
||||
number. For example, `/v2` in `example.com/mod/v2`. Major version suffixes are
|
||||
required at `v2.0.0` and later and are not allowed at earlier versions. See
|
||||
the section on [Major version suffixes](#major-version-suffixes).
|
||||
|
||||
<a id="glos-minimal-version-selection"></a>
|
||||
**minimal version selection (MVS):** The algorithm used to determine the
|
||||
versions of all modules that will be used in a build. See the section on
|
||||
[Minimal version selection](#minimal-version-selection) for details.
|
||||
|
||||
<a id="glos-minor-version"></a>
|
||||
**minor version:** The second number in a semantic version (`2` in `v1.2.3`). In
|
||||
a release with new, backwards compatible functionality, the minor version must
|
||||
be incremented, and the patch version must be set to 0.
|
||||
|
||||
<a id="glos-module"></a>
|
||||
**module:** A collection of packages that are released, versioned, and
|
||||
distributed together.
|
||||
|
||||
<a id="glos-module-graph"></a>
|
||||
**module graph:** The directed graph of module requirements, rooted at the [main
|
||||
module](#glos-main-module). Each vertex in the graph is a module; each edge is a
|
||||
version from a `require` statement in a `go.mod` file (subject to `replace` and
|
||||
`exclude` statements in the main module's `go.mod` file.
|
||||
|
||||
<a id="glos-module-path"></a>
|
||||
**module path:** A path that identifies a module and acts as a prefix for
|
||||
package import paths within the module. For example, `"golang.org/x/net"`.
|
||||
|
||||
<a id="glos-module-proxy"></a>
|
||||
**module proxy:** A web server that implements the [`GOPROXY`
|
||||
protocol](#goproxy-protocol). The `go` command downloads version information,
|
||||
`go.mod` files, and module zip files from module proxies.
|
||||
|
||||
<a id="glos-module-root-directory"></a>
|
||||
**module root directory:** The directory that contains the `go.mod` file that
|
||||
defines a module.
|
||||
|
||||
<a id="glos-package"></a>
|
||||
**package:** A collection of source files in the same directory that are
|
||||
compiled together. See the [Packages section](/ref/spec#Packages) in the Go
|
||||
Language Specification.
|
||||
|
||||
<a id="glos-package-path"></a>
|
||||
**package path:** The path that uniquely identifies a package. A package path is
|
||||
a [module path](#glos-module-path) joined with a subdirectory within the module.
|
||||
For example `"golang.org/x/net/html"` is the package path for the package in the
|
||||
module `"golang.org/x/net"` in the `"html"` subdirectory. Synonym of
|
||||
[import path](#glos-import-path).
|
||||
|
||||
<a id="glos-patch-version"></a>
|
||||
**patch version:** The third number in a semantic version (`3` in `v1.2.3`). In
|
||||
a release with no changes to the module's public interface, the patch version
|
||||
must be incremented.
|
||||
|
||||
<a id="glos-pre-release-version"></a>
|
||||
**pre-release version:** A version with a dash followed by a series of
|
||||
dot-separated identifiers immediately following the patch version, for example,
|
||||
`v1.2.3-beta4`. Pre-release versions are considered unstable and are not
|
||||
assumed to be compatible with other versions. A pre-release version sorts before
|
||||
the corresponding release version: `v1.2.3-pre` comes before `v1.2.3`. See also
|
||||
[release version](#glos-release-version).
|
||||
|
||||
<a id="glos-pseudo-version"></a>
|
||||
**pseudo-version:** A version that encodes a revision identifier (such as a Git
|
||||
commit hash) and a timestamp from a version control system. For example,
|
||||
`v0.0.0-20191109021931-daa7c04131f5`. Used for [compatibility with non-module
|
||||
repositories](#non-module-compat) and in other situations when a tagged
|
||||
version is not available.
|
||||
|
||||
<a id="glos-release-version"></a>
|
||||
**release version:** A version without a pre-release suffix. For example,
|
||||
`v1.2.3`, not `v1.2.3-pre`. See also [pre-release
|
||||
version](#glos-pre-release-version).
|
||||
|
||||
<a id="glos-version"></a>
|
||||
**version:** An identifier for an immutable snapshot of a module, written as the
|
||||
letter `v` followed by a semantic version. See the section on
|
||||
[Versions](#versions).
|
||||
|
|
|
|||
|
|
@ -8,8 +8,8 @@
|
|||
# Consult https://www.iana.org/time-zones for the latest versions.
|
||||
|
||||
# Versions to use.
|
||||
CODE=2019b
|
||||
DATA=2019b
|
||||
CODE=2019c
|
||||
DATA=2019c
|
||||
|
||||
set -e
|
||||
rm -rf work
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -28,7 +28,7 @@ case "$FC" in
|
|||
;;
|
||||
esac
|
||||
|
||||
if ! $FC helloworld/helloworld.f90 -o main.exe >& /dev/null; then
|
||||
if ! $FC helloworld/helloworld.f90 -o /dev/null >& /dev/null; then
|
||||
echo "skipping Fortran test: could not build helloworld.f90 with $FC"
|
||||
exit 0
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,14 +36,21 @@ thread(void *p)
|
|||
import "C"
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
start := time.Now()
|
||||
|
||||
// ensure that we can function normally
|
||||
var v [][]byte
|
||||
for i := 0; i < 1000; i++ {
|
||||
time.Sleep(10 * time.Microsecond)
|
||||
v = append(v, make([]byte, 64<<10))
|
||||
}
|
||||
|
||||
fmt.Printf("ok\t%s\t%s\n", filepath.Base(os.Args[0]), time.Since(start).Round(time.Millisecond))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,10 @@ var exeSuffix string
|
|||
var GOOS, GOARCH, GOPATH string
|
||||
var libgodir string
|
||||
|
||||
var testWork bool // If true, preserve temporary directories.
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
flag.BoolVar(&testWork, "testwork", false, "if true, log and preserve the test's temporary working directory")
|
||||
flag.Parse()
|
||||
if testing.Short() && os.Getenv("GO_BUILDER_NAME") == "" {
|
||||
fmt.Printf("SKIP - short mode and $GO_BUILDER_NAME not set\n")
|
||||
|
|
@ -54,7 +57,11 @@ func testMain(m *testing.M) int {
|
|||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
defer os.RemoveAll(GOPATH)
|
||||
if testWork {
|
||||
log.Println(GOPATH)
|
||||
} else {
|
||||
defer os.RemoveAll(GOPATH)
|
||||
}
|
||||
os.Setenv("GOPATH", GOPATH)
|
||||
|
||||
// Copy testdata into GOPATH/src/testarchive, along with a go.mod file
|
||||
|
|
@ -164,6 +171,38 @@ func cmdToRun(name string) []string {
|
|||
return []string{executor, name}
|
||||
}
|
||||
|
||||
// genHeader writes a C header file for the C-exported declarations found in .go
|
||||
// source files in dir.
|
||||
//
|
||||
// TODO(golang.org/issue/35715): This should be simpler.
|
||||
func genHeader(t *testing.T, header, dir string) {
|
||||
t.Helper()
|
||||
|
||||
// The 'cgo' command generates a number of additional artifacts,
|
||||
// but we're only interested in the header.
|
||||
// Shunt the rest of the outputs to a temporary directory.
|
||||
objDir, err := ioutil.TempDir(GOPATH, "_obj")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(objDir)
|
||||
|
||||
files, err := filepath.Glob(filepath.Join(dir, "*.go"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "tool", "cgo",
|
||||
"-objdir", objDir,
|
||||
"-exportheader", header)
|
||||
cmd.Args = append(cmd.Args, files...)
|
||||
t.Log(cmd.Args)
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
||||
t.Helper()
|
||||
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
|
||||
|
|
@ -172,10 +211,12 @@ func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
|||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer func() {
|
||||
os.Remove(libgoa)
|
||||
os.Remove(libgoh)
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove(libgoa)
|
||||
os.Remove(libgoh)
|
||||
}()
|
||||
}
|
||||
|
||||
ccArgs := append(cc, "-o", exe, "main.c")
|
||||
if GOOS == "windows" {
|
||||
|
|
@ -191,7 +232,9 @@ func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) {
|
|||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(exe)
|
||||
if !testWork {
|
||||
defer os.Remove(exe)
|
||||
}
|
||||
|
||||
binArgs := append(cmdToRun(exe), "arg1", "arg2")
|
||||
cmd = exec.Command(binArgs[0], binArgs[1:]...)
|
||||
|
|
@ -227,17 +270,27 @@ func checkLineComments(t *testing.T, hdrname string) {
|
|||
}
|
||||
|
||||
func TestInstall(t *testing.T) {
|
||||
defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
if !testWork {
|
||||
defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}
|
||||
|
||||
libgoa := "libgo.a"
|
||||
if runtime.Compiler == "gccgo" {
|
||||
libgoa = "liblibgo.a"
|
||||
}
|
||||
|
||||
// Generate the p.h header file.
|
||||
//
|
||||
// 'go install -i -buildmode=c-archive ./libgo' would do that too, but that
|
||||
// would also attempt to install transitive standard-library dependencies to
|
||||
// GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may
|
||||
// be running this test in a GOROOT owned by root.)
|
||||
genHeader(t, "p.h", "./p")
|
||||
|
||||
testInstall(t, "./testp1"+exeSuffix,
|
||||
filepath.Join(libgodir, libgoa),
|
||||
filepath.Join(libgodir, "libgo.h"),
|
||||
"go", "install", "-i", "-buildmode=c-archive", "./libgo")
|
||||
"go", "install", "-buildmode=c-archive", "./libgo")
|
||||
|
||||
// Test building libgo other than installing it.
|
||||
// Header files are now present.
|
||||
|
|
@ -259,12 +312,14 @@ func TestEarlySignalHandler(t *testing.T) {
|
|||
t.Skip("skipping signal test on Windows")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
@ -297,12 +352,14 @@ func TestEarlySignalHandler(t *testing.T) {
|
|||
func TestSignalForwarding(t *testing.T) {
|
||||
checkSignalForwardingTest(t)
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
@ -345,12 +402,14 @@ func TestSignalForwardingExternal(t *testing.T) {
|
|||
}
|
||||
checkSignalForwardingTest(t)
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "./libgo2")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
@ -460,12 +519,14 @@ func TestOsSignal(t *testing.T) {
|
|||
t.Skip("skipping signal test on Windows")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo3.a")
|
||||
os.Remove("libgo3.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo3.a")
|
||||
os.Remove("libgo3.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "./libgo3")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
@ -495,12 +556,14 @@ func TestSigaltstack(t *testing.T) {
|
|||
t.Skip("skipping signal test on Windows")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo4.a")
|
||||
os.Remove("libgo4.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo4.a")
|
||||
os.Remove("libgo4.h")
|
||||
os.Remove("testp")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "./libgo4")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
@ -544,13 +607,15 @@ func TestExtar(t *testing.T) {
|
|||
t.Skip("shell scripts are not executable on iOS hosts")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo4.a")
|
||||
os.Remove("libgo4.h")
|
||||
os.Remove("testar")
|
||||
os.Remove("testar.ran")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo4.a")
|
||||
os.Remove("libgo4.h")
|
||||
os.Remove("testar")
|
||||
os.Remove("testar.ran")
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
os.Remove("testar")
|
||||
dir, err := os.Getwd()
|
||||
|
|
@ -584,12 +649,22 @@ func TestPIE(t *testing.T) {
|
|||
t.Skipf("skipping PIE test on %s", GOOS)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
os.Remove("testp" + exeSuffix)
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("testp" + exeSuffix)
|
||||
os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "install", "-i", "-buildmode=c-archive", "./libgo")
|
||||
// Generate the p.h header file.
|
||||
//
|
||||
// 'go install -i -buildmode=c-archive ./libgo' would do that too, but that
|
||||
// would also attempt to install transitive standard-library dependencies to
|
||||
// GOROOT, and we cannot assume that GOROOT is writable. (A non-root user may
|
||||
// be running this test in a GOROOT owned by root.)
|
||||
genHeader(t, "p.h", "./p")
|
||||
|
||||
cmd := exec.Command("go", "install", "-buildmode=c-archive", "./libgo")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
|
|
@ -669,11 +744,13 @@ func TestSIGPROF(t *testing.T) {
|
|||
|
||||
t.Parallel()
|
||||
|
||||
defer func() {
|
||||
os.Remove("testp6" + exeSuffix)
|
||||
os.Remove("libgo6.a")
|
||||
os.Remove("libgo6.h")
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("testp6" + exeSuffix)
|
||||
os.Remove("libgo6.a")
|
||||
os.Remove("libgo6.h")
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "./libgo6")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
@ -709,10 +786,12 @@ func TestCompileWithoutShared(t *testing.T) {
|
|||
// For simplicity, reuse the signal forwarding test.
|
||||
checkSignalForwardingTest(t)
|
||||
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("libgo2.a")
|
||||
os.Remove("libgo2.h")
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "./libgo2")
|
||||
t.Log(cmd.Args)
|
||||
|
|
@ -751,7 +830,9 @@ func TestCompileWithoutShared(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(exe)
|
||||
if !testWork {
|
||||
defer os.Remove(exe)
|
||||
}
|
||||
|
||||
binArgs := append(cmdToRun(exe), "1")
|
||||
t.Log(binArgs)
|
||||
|
|
@ -769,14 +850,15 @@ func TestCompileWithoutShared(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that installing a second time recreates the header files.
|
||||
// Test that installing a second time recreates the header file.
|
||||
func TestCachedInstall(t *testing.T) {
|
||||
defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
if !testWork {
|
||||
defer os.RemoveAll(filepath.Join(GOPATH, "pkg"))
|
||||
}
|
||||
|
||||
h1 := filepath.Join(libgodir, "libgo.h")
|
||||
h2 := filepath.Join(libgodir, "p.h")
|
||||
h := filepath.Join(libgodir, "libgo.h")
|
||||
|
||||
buildcmd := []string{"go", "install", "-i", "-buildmode=c-archive", "./libgo"}
|
||||
buildcmd := []string{"go", "install", "-buildmode=c-archive", "./libgo"}
|
||||
|
||||
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
|
||||
t.Log(buildcmd)
|
||||
|
|
@ -785,17 +867,11 @@ func TestCachedInstall(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(h1); err != nil {
|
||||
if _, err := os.Stat(h); err != nil {
|
||||
t.Errorf("libgo.h not installed: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(h2); err != nil {
|
||||
t.Errorf("p.h not installed: %v", err)
|
||||
}
|
||||
|
||||
if err := os.Remove(h1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Remove(h2); err != nil {
|
||||
if err := os.Remove(h); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -806,23 +882,22 @@ func TestCachedInstall(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if _, err := os.Stat(h1); err != nil {
|
||||
if _, err := os.Stat(h); err != nil {
|
||||
t.Errorf("libgo.h not installed in second run: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(h2); err != nil {
|
||||
t.Errorf("p.h not installed in second run: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 35294.
|
||||
func TestManyCalls(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
defer func() {
|
||||
os.Remove("testp7" + exeSuffix)
|
||||
os.Remove("libgo7.a")
|
||||
os.Remove("libgo7.h")
|
||||
}()
|
||||
if !testWork {
|
||||
defer func() {
|
||||
os.Remove("testp7" + exeSuffix)
|
||||
os.Remove("libgo7.a")
|
||||
os.Remove("libgo7.h")
|
||||
}()
|
||||
}
|
||||
|
||||
cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo7.a", "./libgo7")
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,8 +130,6 @@ func testMain(m *testing.M) int {
|
|||
defer os.RemoveAll(GOPATH)
|
||||
os.Setenv("GOPATH", GOPATH)
|
||||
|
||||
// Copy testdata into GOPATH/src/testarchive, along with a go.mod file
|
||||
// declaring the same path.
|
||||
modRoot := filepath.Join(GOPATH, "src", "testcshared")
|
||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||
log.Panic(err)
|
||||
|
|
@ -257,14 +255,38 @@ func runCC(t *testing.T, args ...string) string {
|
|||
}
|
||||
|
||||
func createHeaders() error {
|
||||
args := []string{"go", "install", "-i", "-buildmode=c-shared",
|
||||
"-installsuffix", "testcshared", "./libgo"}
|
||||
// The 'cgo' command generates a number of additional artifacts,
|
||||
// but we're only interested in the header.
|
||||
// Shunt the rest of the outputs to a temporary directory.
|
||||
objDir, err := ioutil.TempDir("", "testcshared_obj")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer os.RemoveAll(objDir)
|
||||
|
||||
// Generate a C header file for p, which is a non-main dependency
|
||||
// of main package libgo.
|
||||
//
|
||||
// TODO(golang.org/issue/35715): This should be simpler.
|
||||
args := []string{"go", "tool", "cgo",
|
||||
"-objdir", objDir,
|
||||
"-exportheader", "p.h",
|
||||
filepath.Join(".", "p", "p.go")}
|
||||
cmd := exec.Command(args[0], args[1:]...)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||
}
|
||||
|
||||
// Generate a C header file for libgo itself.
|
||||
args = []string{"go", "install", "-buildmode=c-shared",
|
||||
"-installsuffix", "testcshared", "./libgo"}
|
||||
cmd = exec.Command(args[0], args[1:]...)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||
}
|
||||
|
||||
args = []string{"go", "build", "-buildmode=c-shared",
|
||||
"-installsuffix", "testcshared",
|
||||
"-o", libgoname,
|
||||
|
|
@ -522,7 +544,7 @@ func TestPIE(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Test that installing a second time recreates the header files.
|
||||
// Test that installing a second time recreates the header file.
|
||||
func TestCachedInstall(t *testing.T) {
|
||||
tmpdir, err := ioutil.TempDir("", "cshared")
|
||||
if err != nil {
|
||||
|
|
@ -536,7 +558,7 @@ func TestCachedInstall(t *testing.T) {
|
|||
|
||||
env := append(os.Environ(), "GOPATH="+tmpdir, "GOBIN="+filepath.Join(tmpdir, "bin"))
|
||||
|
||||
buildcmd := []string{"go", "install", "-x", "-i", "-buildmode=c-shared", "-installsuffix", "testcshared", "./libgo"}
|
||||
buildcmd := []string{"go", "install", "-x", "-buildmode=c-shared", "-installsuffix", "testcshared", "./libgo"}
|
||||
|
||||
cmd := exec.Command(buildcmd[0], buildcmd[1:]...)
|
||||
cmd.Dir = filepath.Join(tmpdir, "src", "testcshared")
|
||||
|
|
@ -577,16 +599,10 @@ func TestCachedInstall(t *testing.T) {
|
|||
if libgoh == "" {
|
||||
t.Fatal("libgo.h not installed")
|
||||
}
|
||||
if ph == "" {
|
||||
t.Fatal("p.h not installed")
|
||||
}
|
||||
|
||||
if err := os.Remove(libgoh); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Remove(ph); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = exec.Command(buildcmd[0], buildcmd[1:]...)
|
||||
cmd.Dir = filepath.Join(tmpdir, "src", "testcshared")
|
||||
|
|
@ -601,9 +617,6 @@ func TestCachedInstall(t *testing.T) {
|
|||
if _, err := os.Stat(libgoh); err != nil {
|
||||
t.Errorf("libgo.h not installed in second run: %v", err)
|
||||
}
|
||||
if _, err := os.Stat(ph); err != nil {
|
||||
t.Errorf("p.h not installed in second run: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// copyFile copies src to dst.
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ func testMain(m *testing.M) int {
|
|||
|
||||
os.Setenv("LD_LIBRARY_PATH", modRoot)
|
||||
|
||||
goCmd(nil, "build", "-i", "-buildmode=plugin", "./plugin1")
|
||||
goCmd(nil, "build", "-buildmode=plugin", "./plugin1")
|
||||
goCmd(nil, "build", "-buildmode=plugin", "./plugin2")
|
||||
so, err := ioutil.ReadFile("plugin2.so")
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,31 +9,33 @@ import (
|
|||
"bytes"
|
||||
"debug/elf"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"go/build"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var gopathInstallDir, gorootInstallDir, suffix string
|
||||
var gopathInstallDir, gorootInstallDir string
|
||||
|
||||
// This is the smallest set of packages we can link into a shared
|
||||
// library (runtime/cgo is built implicitly).
|
||||
var minpkgs = []string{"runtime", "sync/atomic"}
|
||||
var soname = "libruntime,sync-atomic.so"
|
||||
|
||||
var testX = flag.Bool("testx", false, "if true, pass -x to 'go' subcommands invoked by the test")
|
||||
var testWork = flag.Bool("testwork", false, "if true, log and do not delete the temporary working directory")
|
||||
|
||||
// run runs a command and calls t.Errorf if it fails.
|
||||
func run(t *testing.T, msg string, args ...string) {
|
||||
c := exec.Command(args[0], args[1:]...)
|
||||
|
|
@ -45,31 +47,34 @@ func run(t *testing.T, msg string, args ...string) {
|
|||
// goCmd invokes the go tool with the installsuffix set up by TestMain. It calls
|
||||
// t.Fatalf if the command fails.
|
||||
func goCmd(t *testing.T, args ...string) string {
|
||||
newargs := []string{args[0], "-installsuffix=" + suffix}
|
||||
if testing.Verbose() {
|
||||
newargs := []string{args[0]}
|
||||
if *testX {
|
||||
newargs = append(newargs, "-x")
|
||||
}
|
||||
newargs = append(newargs, args[1:]...)
|
||||
c := exec.Command("go", newargs...)
|
||||
|
||||
stderr := new(strings.Builder)
|
||||
var output []byte
|
||||
var err error
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ go %s\n", strings.Join(args, " "))
|
||||
c.Stderr = stderr
|
||||
|
||||
if testing.Verbose() && t == nil {
|
||||
fmt.Fprintf(os.Stderr, "+ go %s\n", strings.Join(args, " "))
|
||||
c.Stderr = os.Stderr
|
||||
stderr.WriteString("(output above)")
|
||||
} else {
|
||||
c.Stderr = stderr
|
||||
}
|
||||
output, err = c.Output()
|
||||
output, err := c.Output()
|
||||
|
||||
if err != nil {
|
||||
if t != nil {
|
||||
t.Helper()
|
||||
t.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr)
|
||||
} else {
|
||||
log.Fatalf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr)
|
||||
// Panic instead of using log.Fatalf so that deferred cleanup may run in testMain.
|
||||
log.Panicf("executing %s failed %v:\n%s", strings.Join(c.Args, " "), err, stderr)
|
||||
}
|
||||
}
|
||||
if testing.Verbose() && t != nil {
|
||||
t.Logf("go %s", strings.Join(args, " "))
|
||||
if stderr.Len() > 0 {
|
||||
t.Logf("%s", stderr)
|
||||
}
|
||||
}
|
||||
return string(bytes.TrimSpace(output))
|
||||
|
|
@ -77,73 +82,61 @@ func goCmd(t *testing.T, args ...string) string {
|
|||
|
||||
// TestMain calls testMain so that the latter can use defer (TestMain exits with os.Exit).
|
||||
func testMain(m *testing.M) (int, error) {
|
||||
// Because go install -buildmode=shared $standard_library_package always
|
||||
// installs into $GOROOT, here are some gymnastics to come up with a unique
|
||||
// installsuffix to use in this test that we can clean up afterwards.
|
||||
workDir, err := ioutil.TempDir("", "shared_test")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if *testWork || testing.Verbose() {
|
||||
fmt.Printf("+ mkdir -p %s\n", workDir)
|
||||
}
|
||||
if !*testWork {
|
||||
defer os.RemoveAll(workDir)
|
||||
}
|
||||
|
||||
// Some tests need to edit the source in GOPATH, so copy this directory to a
|
||||
// temporary directory and chdir to that.
|
||||
gopath := filepath.Join(workDir, "gopath")
|
||||
modRoot, err := cloneTestdataModule(gopath)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ export GOPATH=%s\n", gopath)
|
||||
fmt.Printf("+ cd %s\n", modRoot)
|
||||
}
|
||||
os.Setenv("GOPATH", gopath)
|
||||
os.Chdir(modRoot)
|
||||
os.Setenv("PWD", modRoot)
|
||||
|
||||
// The test also needs to install libraries into GOROOT/pkg, so copy the
|
||||
// subset of GOROOT that we need.
|
||||
//
|
||||
// TODO(golang.org/issue/28553): Rework -buildmode=shared so that it does not
|
||||
// need to write to GOROOT.
|
||||
goroot := filepath.Join(workDir, "goroot")
|
||||
if err := cloneGOROOTDeps(goroot); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Fprintf(os.Stderr, "+ export GOROOT=%s\n", goroot)
|
||||
}
|
||||
os.Setenv("GOROOT", goroot)
|
||||
|
||||
myContext := build.Default
|
||||
myContext.GOROOT = goroot
|
||||
myContext.GOPATH = gopath
|
||||
runtimeP, err := myContext.Import("runtime", ".", build.ImportComment)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("import failed: %v", err)
|
||||
}
|
||||
for i := 0; i < 10000; i++ {
|
||||
try := fmt.Sprintf("%s_%d_dynlink", runtimeP.PkgTargetRoot, rand.Int63())
|
||||
err = os.Mkdir(try, 0700)
|
||||
if os.IsExist(err) {
|
||||
continue
|
||||
}
|
||||
if err == nil {
|
||||
gorootInstallDir = try
|
||||
}
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("can't create temporary directory: %v", err)
|
||||
}
|
||||
if gorootInstallDir == "" {
|
||||
return 0, errors.New("could not create temporary directory after 10000 tries")
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ mkdir -p %s\n", gorootInstallDir)
|
||||
}
|
||||
defer os.RemoveAll(gorootInstallDir)
|
||||
|
||||
// Some tests need to edit the source in GOPATH, so copy this directory to a
|
||||
// temporary directory and chdir to that.
|
||||
gopath, err := ioutil.TempDir("", "testshared")
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("TempDir failed: %v", err)
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ mkdir -p %s\n", gopath)
|
||||
}
|
||||
defer os.RemoveAll(gopath)
|
||||
|
||||
modRoot := filepath.Join(gopath, "src", "testshared")
|
||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ cd %s\n", modRoot)
|
||||
}
|
||||
os.Chdir(modRoot)
|
||||
os.Setenv("PWD", modRoot)
|
||||
if err := ioutil.WriteFile("go.mod", []byte("module testshared\n"), 0666); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
os.Setenv("GOPATH", gopath)
|
||||
if testing.Verbose() {
|
||||
fmt.Printf("+ export GOPATH=%s\n", gopath)
|
||||
}
|
||||
myContext.GOPATH = gopath
|
||||
gorootInstallDir = runtimeP.PkgTargetRoot + "_dynlink"
|
||||
|
||||
// All tests depend on runtime being built into a shared library. Because
|
||||
// that takes a few seconds, do it here and have all tests use the version
|
||||
// built here.
|
||||
suffix = strings.Split(filepath.Base(gorootInstallDir), "_")[2]
|
||||
goCmd(nil, append([]string{"install", "-buildmode=shared"}, minpkgs...)...)
|
||||
|
||||
myContext.InstallSuffix = suffix + "_dynlink"
|
||||
myContext.InstallSuffix = "_dynlink"
|
||||
depP, err := myContext.Import("./depBase", ".", build.ImportComment)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("import failed: %v", err)
|
||||
|
|
@ -171,6 +164,75 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
// cloneTestdataModule clones the packages from src/testshared into gopath.
|
||||
// It returns the directory within gopath at which the module root is located.
|
||||
func cloneTestdataModule(gopath string) (string, error) {
|
||||
modRoot := filepath.Join(gopath, "src", "testshared")
|
||||
if err := overlayDir(modRoot, "testdata"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
if err := ioutil.WriteFile(filepath.Join(modRoot, "go.mod"), []byte("module testshared\n"), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return modRoot, nil
|
||||
}
|
||||
|
||||
// cloneGOROOTDeps copies (or symlinks) the portions of GOROOT/src and
|
||||
// GOROOT/pkg relevant to this test into the given directory.
|
||||
// It must be run from within the testdata module.
|
||||
func cloneGOROOTDeps(goroot string) error {
|
||||
oldGOROOT := strings.TrimSpace(goCmd(nil, "env", "GOROOT"))
|
||||
if oldGOROOT == "" {
|
||||
return fmt.Errorf("go env GOROOT returned an empty string")
|
||||
}
|
||||
|
||||
// Before we clone GOROOT, figure out which packages we need to copy over.
|
||||
listArgs := []string{
|
||||
"list",
|
||||
"-deps",
|
||||
"-f", "{{if and .Standard (not .ForTest)}}{{.ImportPath}}{{end}}",
|
||||
}
|
||||
stdDeps := goCmd(nil, append(listArgs, minpkgs...)...)
|
||||
testdataDeps := goCmd(nil, append(listArgs, "-test", "./...")...)
|
||||
|
||||
pkgs := append(strings.Split(strings.TrimSpace(stdDeps), "\n"),
|
||||
strings.Split(strings.TrimSpace(testdataDeps), "\n")...)
|
||||
sort.Strings(pkgs)
|
||||
var pkgRoots []string
|
||||
for _, pkg := range pkgs {
|
||||
parentFound := false
|
||||
for _, prev := range pkgRoots {
|
||||
if strings.HasPrefix(pkg, prev) {
|
||||
// We will copy in the source for pkg when we copy in prev.
|
||||
parentFound = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !parentFound {
|
||||
pkgRoots = append(pkgRoots, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
gorootDirs := []string{
|
||||
"pkg/tool",
|
||||
"pkg/include",
|
||||
}
|
||||
for _, pkg := range pkgRoots {
|
||||
gorootDirs = append(gorootDirs, filepath.Join("src", pkg))
|
||||
}
|
||||
|
||||
for _, dir := range gorootDirs {
|
||||
if testing.Verbose() {
|
||||
fmt.Fprintf(os.Stderr, "+ cp -r %s %s\n", filepath.Join(goroot, dir), filepath.Join(oldGOROOT, dir))
|
||||
}
|
||||
if err := overlayDir(filepath.Join(goroot, dir), filepath.Join(oldGOROOT, dir)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// The shared library was built at the expected location.
|
||||
func TestSOBuilt(t *testing.T) {
|
||||
_, err := os.Stat(filepath.Join(gorootInstallDir, soname))
|
||||
|
|
@ -219,6 +281,7 @@ func TestNoTextrel(t *testing.T) {
|
|||
}
|
||||
|
||||
// The shared library does not contain symbols called ".dup"
|
||||
// (See golang.org/issue/14841.)
|
||||
func TestNoDupSymbols(t *testing.T) {
|
||||
sopath := filepath.Join(gorootInstallDir, soname)
|
||||
f, err := elf.Open(sopath)
|
||||
|
|
@ -695,7 +758,7 @@ func resetFileStamps() {
|
|||
}
|
||||
reset := func(path string) {
|
||||
if err := filepath.Walk(path, chtime); err != nil {
|
||||
log.Fatalf("resetFileStamps failed: %v", err)
|
||||
log.Panicf("resetFileStamps failed: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -708,6 +771,7 @@ func resetFileStamps() {
|
|||
// touch changes path and returns a function that changes it back.
|
||||
// It also sets the time of the file, so that we can see if it is rewritten.
|
||||
func touch(t *testing.T, path string) (cleanup func()) {
|
||||
t.Helper()
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -736,14 +800,32 @@ func touch(t *testing.T, path string) (cleanup func()) {
|
|||
// assume it's a text file
|
||||
data = append(data, '\n')
|
||||
}
|
||||
if err := ioutil.WriteFile(path, data, 0666); err != nil {
|
||||
|
||||
// If the file is still a symlink from an overlay, delete it so that we will
|
||||
// replace it with a regular file instead of overwriting the symlinked one.
|
||||
fi, err := os.Lstat(path)
|
||||
if err == nil && !fi.Mode().IsRegular() {
|
||||
fi, err = os.Stat(path)
|
||||
if err := os.Remove(path); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// If we're replacing a symlink to a read-only file, make the new file
|
||||
// user-writable.
|
||||
perm := fi.Mode().Perm() | 0200
|
||||
|
||||
if err := ioutil.WriteFile(path, data, perm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.Chtimes(path, nearlyNew, nearlyNew); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return func() {
|
||||
if err := ioutil.WriteFile(path, old, 0666); err != nil {
|
||||
if err := ioutil.WriteFile(path, old, perm); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ static void sigsegv() {
|
|||
|
||||
static void segvhandler(int signum) {
|
||||
if (signum == SIGSEGV) {
|
||||
fprintf(stdout, "ok\ttestsigfwd\n");
|
||||
exit(0); // success
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,9 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
symBase, err := filepath.Rel(srcRoot, dstRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
symBase, err = filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error {
|
||||
|
|
@ -52,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
chrome.omnibox.onInputEntered.addListener(function(t) {
|
||||
var url = urlForInput(t);
|
||||
if (url) {
|
||||
chrome.tabs.getSelected(null, function(tab) {
|
||||
chrome.tabs.query({ "active": true, "currentWindow": true }, function(tab) {
|
||||
if (!tab) return;
|
||||
chrome.tabs.update(tab.id, { "url": url, "selected": true });
|
||||
});
|
||||
|
|
|
|||
|
|
@ -21,9 +21,7 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// If we don't use the absolute path here, exec'ing make.bash fails with
|
||||
// “too many levels of symbolic links”.
|
||||
symBase, err := filepath.Abs(srcRoot)
|
||||
srcRoot, err := filepath.Abs(srcRoot)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -51,11 +49,11 @@ func overlayDir(dstRoot, srcRoot string) error {
|
|||
// Always copy directories (don't symlink them).
|
||||
// If we add a file in the overlay, we don't want to add it in the original.
|
||||
if info.IsDir() {
|
||||
return os.Mkdir(dstPath, perm|0200)
|
||||
return os.MkdirAll(dstPath, perm|0200)
|
||||
}
|
||||
|
||||
// If the OS supports symlinks, use them instead of copying bytes.
|
||||
if err := os.Symlink(filepath.Join(symBase, suffix), dstPath); err == nil {
|
||||
if err := os.Symlink(srcPath, dstPath); err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"internal/obscuretestdata"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
@ -19,11 +20,12 @@ import (
|
|||
)
|
||||
|
||||
type ZipTest struct {
|
||||
Name string
|
||||
Source func() (r io.ReaderAt, size int64) // if non-nil, used instead of testdata/<Name> file
|
||||
Comment string
|
||||
File []ZipTestFile
|
||||
Error error // the error that Opening this file should return
|
||||
Name string
|
||||
Source func() (r io.ReaderAt, size int64) // if non-nil, used instead of testdata/<Name> file
|
||||
Comment string
|
||||
File []ZipTestFile
|
||||
Obscured bool // needed for Apple notarization (golang.org/issue/34986)
|
||||
Error error // the error that Opening this file should return
|
||||
}
|
||||
|
||||
type ZipTestFile struct {
|
||||
|
|
@ -189,8 +191,12 @@ var tests = []ZipTest{
|
|||
},
|
||||
{
|
||||
// created by Go, before we wrote the "optional" data
|
||||
// descriptor signatures (which are required by OS X)
|
||||
Name: "go-no-datadesc-sig.zip",
|
||||
// descriptor signatures (which are required by macOS).
|
||||
// Use obscured file to avoid Apple’s notarization service
|
||||
// rejecting the toolchain due to an inability to unzip this archive.
|
||||
// See golang.org/issue/34986
|
||||
Name: "go-no-datadesc-sig.zip.base64",
|
||||
Obscured: true,
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
Name: "foo.txt",
|
||||
|
|
@ -208,7 +214,7 @@ var tests = []ZipTest{
|
|||
},
|
||||
{
|
||||
// created by Go, after we wrote the "optional" data
|
||||
// descriptor signatures (which are required by OS X)
|
||||
// descriptor signatures (which are required by macOS)
|
||||
Name: "go-with-datadesc-sig.zip",
|
||||
File: []ZipTestFile{
|
||||
{
|
||||
|
|
@ -496,8 +502,18 @@ func readTestZip(t *testing.T, zt ZipTest) {
|
|||
rat, size := zt.Source()
|
||||
z, err = NewReader(rat, size)
|
||||
} else {
|
||||
path := filepath.Join("testdata", zt.Name)
|
||||
if zt.Obscured {
|
||||
tf, err := obscuretestdata.DecodeToTempFile(path)
|
||||
if err != nil {
|
||||
t.Errorf("obscuretestdata.DecodeToTempFile(%s): %v", path, err)
|
||||
return
|
||||
}
|
||||
defer os.Remove(tf)
|
||||
path = tf
|
||||
}
|
||||
var rc *ReadCloser
|
||||
rc, err = OpenReader(filepath.Join("testdata", zt.Name))
|
||||
rc, err = OpenReader(path)
|
||||
if err == nil {
|
||||
defer rc.Close()
|
||||
z = &rc.Reader
|
||||
|
|
|
|||
BIN
src/archive/zip/testdata/go-no-datadesc-sig.zip
vendored
BIN
src/archive/zip/testdata/go-no-datadesc-sig.zip
vendored
Binary file not shown.
1
src/archive/zip/testdata/go-no-datadesc-sig.zip.base64
vendored
Normal file
1
src/archive/zip/testdata/go-no-datadesc-sig.zip.base64
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
UEsDBBQACAAAAGWHaECoZTJ+BAAAAAQAAAAHABgAZm9vLnR4dFVUBQAD3lVZT3V4CwABBPUBAAAEFAAAAGZvbwqoZTJ+BAAAAAQAAABQSwMEFAAIAAAAZodoQOmzogQEAAAABAAAAAcAGABiYXIudHh0VVQFAAPgVVlPdXgLAAEE9QEAAAQUAAAAYmFyCumzogQEAAAABAAAAFBLAQIUAxQACAAAAGWHaECoZTJ+BAAAAAQAAAAHABgAAAAAAAAAAACkgQAAAABmb28udHh0VVQFAAPeVVlPdXgLAAEE9QEAAAQUAAAAUEsBAhQDFAAIAAAAZodoQOmzogQEAAAABAAAAAcAGAAAAAAAAAAAAKSBTQAAAGJhci50eHRVVAUAA+BVWU91eAsAAQT1AQAABBQAAABQSwUGAAAAAAIAAgCaAAAAmgAAAAAA
|
||||
|
|
@ -1313,8 +1313,10 @@ func gccgoPkgpathToSymbolNew(ppath string) string {
|
|||
for _, c := range []byte(ppath) {
|
||||
switch {
|
||||
case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z',
|
||||
'0' <= c && c <= '9', c == '_', c == '.':
|
||||
'0' <= c && c <= '9', c == '_':
|
||||
bsl = append(bsl, c)
|
||||
case c == '.':
|
||||
bsl = append(bsl, ".x2e"...)
|
||||
default:
|
||||
changed = true
|
||||
encbytes := []byte(fmt.Sprintf("..z%02x", c))
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ func fmtFlag(s fmt.State, verb rune) FmtFlag {
|
|||
|
||||
// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode
|
||||
const (
|
||||
FErr = iota
|
||||
FErr fmtMode = iota
|
||||
FDbg
|
||||
FTypeId
|
||||
FTypeIdName // same as FTypeId, but use package name instead of prefix
|
||||
|
|
|
|||
|
|
@ -525,7 +525,7 @@ func Main(archInit func(*Arch)) {
|
|||
}
|
||||
types.FmtLeft = int(FmtLeft)
|
||||
types.FmtUnsigned = int(FmtUnsigned)
|
||||
types.FErr = FErr
|
||||
types.FErr = int(FErr)
|
||||
types.Ctxt = Ctxt
|
||||
|
||||
initUniverse()
|
||||
|
|
|
|||
|
|
@ -6041,6 +6041,12 @@ func genssa(f *ssa.Func, pp *Progs) {
|
|||
if s.bstart[b.ID] == s.pp.next && len(b.Succs) == 1 && b.Succs[0].Block() == b {
|
||||
p := thearch.Ginsnop(s.pp)
|
||||
p.Pos = p.Pos.WithIsStmt()
|
||||
if b.Pos == src.NoXPos {
|
||||
b.Pos = p.Pos // It needs a file, otherwise a no-file non-zero line causes confusion. See #35652.
|
||||
if b.Pos == src.NoXPos {
|
||||
b.Pos = pp.Text.Pos // Sometimes p.Pos is empty. See #35695.
|
||||
}
|
||||
}
|
||||
b.Pos = b.Pos.WithBogusLine() // Debuggers are not good about infinite loops, force a change in line number
|
||||
}
|
||||
// Emit control flow instructions for block
|
||||
|
|
|
|||
23
src/cmd/dist/test.go
vendored
23
src/cmd/dist/test.go
vendored
|
|
@ -692,7 +692,7 @@ func (t *tester) registerTests() {
|
|||
t.registerTest("testplugin", "../misc/cgo/testplugin", t.goTest(), t.timeout(600), ".")
|
||||
}
|
||||
if gohostos == "linux" && goarch == "amd64" {
|
||||
t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", "main.go")
|
||||
t.registerTest("testasan", "../misc/cgo/testasan", "go", "run", ".")
|
||||
}
|
||||
if mSanSupported(goos, goarch) {
|
||||
t.registerHostTest("testsanitizers/msan", "../misc/cgo/testsanitizers", "misc/cgo/testsanitizers", ".")
|
||||
|
|
@ -701,7 +701,7 @@ func (t *tester) registerTests() {
|
|||
t.registerHostTest("cgo_errors", "../misc/cgo/errors", "misc/cgo/errors", ".")
|
||||
}
|
||||
if gohostos == "linux" && t.extLink() {
|
||||
t.registerTest("testsigfwd", "../misc/cgo/testsigfwd", "go", "run", "main.go")
|
||||
t.registerTest("testsigfwd", "../misc/cgo/testsigfwd", "go", "run", ".")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1327,7 +1327,6 @@ func (t *tester) runFlag(rx string) string {
|
|||
}
|
||||
|
||||
func (t *tester) raceTest(dt *distTest) error {
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", "-i", "runtime/race", "flag", "os", "os/exec")
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("Output"), "runtime/race")
|
||||
t.addCmd(dt, "src", t.goTest(), "-race", t.runFlag("TestParse|TestEcho|TestStdinCloseRace|TestClosedPipeRace|TestTypeRace|TestFdRace|TestFdReadRace|TestFileCloseRace"), "flag", "net", "os", "os/exec", "encoding/gob")
|
||||
// We don't want the following line, because it
|
||||
|
|
@ -1449,7 +1448,25 @@ func (t *tester) makeGOROOTUnwritable() (undo func()) {
|
|||
}
|
||||
}
|
||||
|
||||
gocache := os.Getenv("GOCACHE")
|
||||
if gocache == "" {
|
||||
panic("GOCACHE not set")
|
||||
}
|
||||
gocacheSubdir, _ := filepath.Rel(dir, gocache)
|
||||
|
||||
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if suffix := strings.TrimPrefix(path, dir+string(filepath.Separator)); suffix != "" {
|
||||
if suffix == gocacheSubdir {
|
||||
// Leave GOCACHE writable: we may need to write test binaries into it.
|
||||
return filepath.SkipDir
|
||||
}
|
||||
if suffix == ".git" {
|
||||
// Leave Git metadata in whatever state it was in. It may contain a lot
|
||||
// of files, and it is highly unlikely that a test will try to modify
|
||||
// anything within that directory.
|
||||
return filepath.SkipDir
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
mode := info.Mode()
|
||||
if mode&0222 != 0 && (mode.IsDir() || mode.IsRegular()) {
|
||||
|
|
|
|||
|
|
@ -203,10 +203,8 @@ func processFile(filename string, useStdin bool) error {
|
|||
return ioutil.WriteFile(f.Name(), newSrc, 0)
|
||||
}
|
||||
|
||||
var gofmtBuf bytes.Buffer
|
||||
|
||||
func gofmt(n interface{}) string {
|
||||
gofmtBuf.Reset()
|
||||
var gofmtBuf bytes.Buffer
|
||||
if err := format.Node(&gofmtBuf, fset, n); err != nil {
|
||||
return "<" + err.Error() + ">"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,7 @@ func parseFixPrint(t *testing.T, fn func(*ast.File) bool, desc, in string, mustB
|
|||
|
||||
func TestRewrite(t *testing.T) {
|
||||
for _, tt := range testCases {
|
||||
tt := tt
|
||||
t.Run(tt.Name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Apply fix: should get tt.Out.
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/ianlancetaylor/demangle v0.0.0-20180524225900-fc6590592b44 // indirect
|
||||
golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee
|
||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792
|
||||
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 // indirect
|
||||
golang.org/x/tools v0.0.0-20191104222624-6b7b8b79ae80
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ golang.org/x/arch v0.0.0-20190815191158-8a70ba74b3a1/go.mod h1:flIaEI6LNU6xOCD5P
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792 h1:04Uqz7R2BD7irAGgQtrKNW5tLa50RgSW71y4ofoaivk=
|
||||
golang.org/x/mod v0.1.1-0.20191126161957-788aebd06792/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -18,8 +18,8 @@ golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82 h1:vsphBvatvfbhlb4PO1BYSr9dz
|
|||
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20191104222624-6b7b8b79ae80 h1:6CcDC1SXj4DrJP955osT9RJmKsH3LQBZJ59D5v4Rw0s=
|
||||
golang.org/x/tools v0.0.0-20191104222624-6b7b8b79ae80/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e h1:aZzprAO9/8oim3qStq3wc1Xuxx4QmAGriC4VU4ojemQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
|||
|
|
@ -1010,7 +1010,7 @@
|
|||
//
|
||||
// Usage:
|
||||
//
|
||||
// go mod download [-json] [modules]
|
||||
// go mod download [-x] [-json] [modules]
|
||||
//
|
||||
// Download downloads the named modules, which can be module patterns selecting
|
||||
// dependencies of the main module or module queries of the form path@version.
|
||||
|
|
@ -1037,6 +1037,8 @@
|
|||
// GoModSum string // checksum for go.mod (as in go.sum)
|
||||
// }
|
||||
//
|
||||
// The -x flag causes download to print the commands download executes.
|
||||
//
|
||||
// See 'go help modules' for more about module queries.
|
||||
//
|
||||
//
|
||||
|
|
|
|||
|
|
@ -683,8 +683,11 @@ func (tg *testgoData) creatingTemp(path string) {
|
|||
// If we have changed the working directory, make sure we have
|
||||
// an absolute path, because we are going to change directory
|
||||
// back before we remove the temporary.
|
||||
if tg.wd != "" && !filepath.IsAbs(path) {
|
||||
path = filepath.Join(tg.pwd(), path)
|
||||
if !filepath.IsAbs(path) {
|
||||
if tg.wd == "" || strings.HasPrefix(tg.wd, testGOROOT) {
|
||||
tg.t.Fatalf("internal testsuite error: creatingTemp(%q) within GOROOT/src", path)
|
||||
}
|
||||
path = filepath.Join(tg.wd, path)
|
||||
}
|
||||
tg.must(robustio.RemoveAll(path))
|
||||
tg.temps = append(tg.temps, path)
|
||||
|
|
@ -943,7 +946,7 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
|||
return err
|
||||
}
|
||||
tg.tempFile(dest, string(data))
|
||||
if err := os.Chmod(tg.path(dest), info.Mode()); err != nil {
|
||||
if err := os.Chmod(tg.path(dest), info.Mode()|0200); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
@ -1008,128 +1011,6 @@ func TestNewReleaseRebuildsStalePackagesInGOPATH(t *testing.T) {
|
|||
tg.wantNotStale("p1", "", "./testgo list claims p1 is stale after building with old release")
|
||||
}
|
||||
|
||||
func testLocalRun(tg *testgoData, exepath, local, match string) {
|
||||
tg.t.Helper()
|
||||
out, err := exec.Command(exepath).Output()
|
||||
if err != nil {
|
||||
tg.t.Fatalf("error running %v: %v", exepath, err)
|
||||
}
|
||||
if !regexp.MustCompile(match).Match(out) {
|
||||
tg.t.Log(string(out))
|
||||
tg.t.Errorf("testdata/%s/easy.go did not generate expected output", local)
|
||||
}
|
||||
}
|
||||
|
||||
func testLocalEasy(tg *testgoData, local string) {
|
||||
tg.t.Helper()
|
||||
exepath := "./easy" + exeSuffix
|
||||
tg.creatingTemp(exepath)
|
||||
tg.run("build", "-o", exepath, filepath.Join("testdata", local, "easy.go"))
|
||||
testLocalRun(tg, exepath, local, `(?m)^easysub\.Hello`)
|
||||
}
|
||||
|
||||
func testLocalEasySub(tg *testgoData, local string) {
|
||||
tg.t.Helper()
|
||||
exepath := "./easysub" + exeSuffix
|
||||
tg.creatingTemp(exepath)
|
||||
tg.run("build", "-o", exepath, filepath.Join("testdata", local, "easysub", "main.go"))
|
||||
testLocalRun(tg, exepath, local, `(?m)^easysub\.Hello`)
|
||||
}
|
||||
|
||||
func testLocalHard(tg *testgoData, local string) {
|
||||
tg.t.Helper()
|
||||
exepath := "./hard" + exeSuffix
|
||||
tg.creatingTemp(exepath)
|
||||
tg.run("build", "-o", exepath, filepath.Join("testdata", local, "hard.go"))
|
||||
testLocalRun(tg, exepath, local, `(?m)^sub\.Hello`)
|
||||
}
|
||||
|
||||
func testLocalInstall(tg *testgoData, local string) {
|
||||
tg.t.Helper()
|
||||
tg.runFail("install", filepath.Join("testdata", local, "easy.go"))
|
||||
}
|
||||
|
||||
func TestLocalImportsEasy(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
testLocalEasy(tg, "local")
|
||||
}
|
||||
|
||||
func TestLocalImportsEasySub(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
testLocalEasySub(tg, "local")
|
||||
}
|
||||
|
||||
func TestLocalImportsHard(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
testLocalHard(tg, "local")
|
||||
}
|
||||
|
||||
func TestLocalImportsGoInstallShouldFail(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
testLocalInstall(tg, "local")
|
||||
}
|
||||
|
||||
const badDirName = `#$%:, &()*;<=>?\^{}`
|
||||
|
||||
func copyBad(tg *testgoData) {
|
||||
tg.t.Helper()
|
||||
if runtime.GOOS == "windows" {
|
||||
tg.t.Skipf("skipping test because %q is an invalid directory name", badDirName)
|
||||
}
|
||||
|
||||
tg.must(filepath.Walk("testdata/local",
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
return nil
|
||||
}
|
||||
var data []byte
|
||||
data, err = ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newpath := strings.Replace(path, "local", badDirName, 1)
|
||||
tg.tempFile(newpath, string(data))
|
||||
return nil
|
||||
}))
|
||||
tg.cd(tg.path("."))
|
||||
}
|
||||
|
||||
func TestBadImportsEasy(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
// TODO: tg.parallel()
|
||||
copyBad(tg)
|
||||
testLocalEasy(tg, badDirName)
|
||||
}
|
||||
|
||||
func TestBadImportsEasySub(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
copyBad(tg)
|
||||
testLocalEasySub(tg, badDirName)
|
||||
}
|
||||
|
||||
func TestBadImportsHard(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
copyBad(tg)
|
||||
testLocalHard(tg, badDirName)
|
||||
}
|
||||
|
||||
func TestBadImportsGoInstallShouldFail(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
copyBad(tg)
|
||||
testLocalInstall(tg, badDirName)
|
||||
}
|
||||
|
||||
func TestInternalPackagesInGOROOTAreRespected(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo does not have GOROOT")
|
||||
tg := testgo(t)
|
||||
|
|
@ -1167,48 +1048,6 @@ func TestRunPkg(t *testing.T) {
|
|||
tg.grepStderr("hello, world", "did not find hello, world")
|
||||
}
|
||||
|
||||
func testMove(t *testing.T, vcs, url, base, config string) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempDir("src")
|
||||
tg.must(os.Mkdir(tg.path(".hg"), 0700))
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.path(".hg"), "hgrc"), nil, 0600))
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.run("get", "-d", url)
|
||||
tg.run("get", "-d", "-u", url)
|
||||
switch vcs {
|
||||
case "svn":
|
||||
// SVN doesn't believe in text files so we can't just edit the config.
|
||||
// Check out a different repo into the wrong place.
|
||||
tg.must(robustio.RemoveAll(tg.path("src/code.google.com/p/rsc-svn")))
|
||||
tg.run("get", "-d", "-u", "code.google.com/p/rsc-svn2/trunk")
|
||||
tg.must(os.Rename(tg.path("src/code.google.com/p/rsc-svn2"), tg.path("src/code.google.com/p/rsc-svn")))
|
||||
default:
|
||||
path := tg.path(filepath.Join("src", config))
|
||||
data, err := ioutil.ReadFile(path)
|
||||
tg.must(err)
|
||||
data = bytes.ReplaceAll(data, []byte(base), []byte(base+"XXX"))
|
||||
tg.must(ioutil.WriteFile(path, data, 0644))
|
||||
}
|
||||
if vcs == "git" {
|
||||
// git will ask for a username and password when we
|
||||
// run go get -d -f -u. An empty username and
|
||||
// password will work. Prevent asking by setting
|
||||
// GIT_ASKPASS.
|
||||
tg.creatingTemp("sink" + exeSuffix)
|
||||
tg.tempFile("src/sink/sink.go", `package main; func main() {}`)
|
||||
tg.run("build", "-o", "sink"+exeSuffix, "sink")
|
||||
tg.setenv("GIT_ASKPASS", filepath.Join(tg.pwd(), "sink"+exeSuffix))
|
||||
}
|
||||
tg.runFail("get", "-d", "-u", url)
|
||||
tg.grepStderr("is a custom import path for", "go get -d -u "+url+" failed for wrong reason")
|
||||
tg.runFail("get", "-d", "-f", "-u", url)
|
||||
tg.grepStderr("validating server certificate|[nN]ot [fF]ound", "go get -d -f -u "+url+" failed for wrong reason")
|
||||
}
|
||||
|
||||
func TestInternalPackageErrorsAreHandled(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -1223,21 +1062,6 @@ func TestInternalCache(t *testing.T) {
|
|||
tg.grepStderr("internal", "did not fail to build p")
|
||||
}
|
||||
|
||||
func TestMoveGit(t *testing.T) {
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
testMove(t, "git", "rsc.io/pdf", "pdf", "rsc.io/pdf/.git/config")
|
||||
}
|
||||
|
||||
func TestMoveHG(t *testing.T) {
|
||||
testenv.MustHaveExecPath(t, "hg")
|
||||
testMove(t, "hg", "vcs-test.golang.org/go/custom-hg-hello", "custom-hg-hello", "vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc")
|
||||
}
|
||||
|
||||
// TODO(rsc): Set up a test case on SourceForge (?) for svn.
|
||||
// func testMoveSVN(t *testing.T) {
|
||||
// testMove(t, "svn", "code.google.com/p/rsc-svn/trunk", "-", "-")
|
||||
// }
|
||||
|
||||
func TestImportCommandMatch(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -1491,72 +1315,6 @@ func TestRelativeGOBINFail(t *testing.T) {
|
|||
tg.grepStderr("cannot install, GOBIN must be an absolute path", "go install must fail if $GOBIN is a relative path")
|
||||
}
|
||||
|
||||
// Test that without $GOBIN set, binaries get installed
|
||||
// into the GOPATH bin directory.
|
||||
func TestInstallIntoGOPATH(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.creatingTemp("testdata/bin/go-cmd-test" + exeSuffix)
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.run("install", "go-cmd-test")
|
||||
tg.wantExecutable("testdata/bin/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin/go-cmd-test")
|
||||
}
|
||||
|
||||
// Issue 12407
|
||||
func TestBuildOutputToDevNull(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
fi1, err1 := os.Lstat(os.DevNull)
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.run("build", "-o", os.DevNull, "go-cmd-test")
|
||||
fi2, err2 := os.Lstat(os.DevNull)
|
||||
if err1 == nil {
|
||||
if err2 != nil {
|
||||
t.Errorf("second stat of /dev/null failed: %v", err2)
|
||||
} else if !os.SameFile(fi1, fi2) {
|
||||
t.Errorf("/dev/null changed: now %v was %v", fi1, fi2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 28549.
|
||||
func TestTestOutputToDevNull(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
fi1, err1 := os.Lstat(os.DevNull)
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.tempFile("src/p/p.go", "package p\n")
|
||||
tg.tempFile("src/p/p_test.go", "package p\nimport \"testing\"\nfunc TestX(t *testing.T) {}\n")
|
||||
tg.run("test", "-o", os.DevNull, "-c", "p")
|
||||
tg.mustNotExist("p.test")
|
||||
fi2, err2 := os.Lstat(os.DevNull)
|
||||
if err1 == nil {
|
||||
if err2 != nil {
|
||||
t.Errorf("second stat of /dev/null failed: %v", err2)
|
||||
} else if !os.SameFile(fi1, fi2) {
|
||||
t.Errorf("/dev/null changed: now %v was %v", fi1, fi2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageMainTestImportsArchiveNotBinary(t *testing.T) {
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
gobin := filepath.Join(tg.pwd(), "testdata", "bin")
|
||||
tg.creatingTemp(gobin)
|
||||
tg.setenv("GOBIN", gobin)
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.must(os.Chtimes("./testdata/src/main_test/m.go", time.Now(), time.Now()))
|
||||
tg.sleep()
|
||||
tg.run("test", "main_test")
|
||||
tg.run("install", "main_test")
|
||||
tg.wantNotStale("main_test", "", "after go install, main listed as stale")
|
||||
tg.run("test", "main_test")
|
||||
}
|
||||
|
||||
func TestPackageMainTestCompilerFlags(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -1589,51 +1347,6 @@ func TestPackageNotStaleWithTrailingSlash(t *testing.T) {
|
|||
tg.wantNotStale("io", "", "with trailing slash in GOROOT, io listed as stale")
|
||||
}
|
||||
|
||||
// With $GOBIN set, binaries get installed to $GOBIN.
|
||||
func TestInstallIntoGOBIN(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
gobin := filepath.Join(tg.pwd(), "testdata", "bin1")
|
||||
tg.creatingTemp(gobin)
|
||||
tg.setenv("GOBIN", gobin)
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.run("install", "go-cmd-test")
|
||||
tg.wantExecutable("testdata/bin1/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin1/go-cmd-test")
|
||||
}
|
||||
|
||||
// Issue 11065
|
||||
func TestInstallToCurrentDirectoryCreatesExecutable(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
pkg := filepath.Join(tg.pwd(), "testdata", "src", "go-cmd-test")
|
||||
tg.creatingTemp(filepath.Join(pkg, "go-cmd-test"+exeSuffix))
|
||||
tg.setenv("GOBIN", pkg)
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.cd(pkg)
|
||||
tg.run("install")
|
||||
tg.wantExecutable("go-cmd-test"+exeSuffix, "go install did not write to current directory")
|
||||
}
|
||||
|
||||
// Without $GOBIN set, installing a program outside $GOPATH should fail
|
||||
// (there is nowhere to install it).
|
||||
func TestInstallWithoutDestinationFails(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.runFail("install", "testdata/src/go-cmd-test/helloworld.go")
|
||||
tg.grepStderr("no install location for .go files listed on command line", "wrong error")
|
||||
}
|
||||
|
||||
// With $GOBIN set, should install there.
|
||||
func TestInstallToGOBINCommandLinePackage(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
gobin := filepath.Join(tg.pwd(), "testdata", "bin1")
|
||||
tg.creatingTemp(gobin)
|
||||
tg.setenv("GOBIN", gobin)
|
||||
tg.run("install", "testdata/src/go-cmd-test/helloworld.go")
|
||||
tg.wantExecutable("testdata/bin1/helloworld"+exeSuffix, "go install testdata/src/go-cmd-test/helloworld.go did not write testdata/bin1/helloworld")
|
||||
}
|
||||
|
||||
func TestGoGetNonPkg(t *testing.T) {
|
||||
testenv.MustHaveExternalNetwork(t)
|
||||
testenv.MustHaveExecPath(t, "git")
|
||||
|
|
@ -1663,94 +1376,6 @@ func TestGoGetTestOnlyPkg(t *testing.T) {
|
|||
tg.run("get", "-t", "golang.org/x/tour/content...")
|
||||
}
|
||||
|
||||
func TestInstalls(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("don't install into GOROOT in short mode")
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempDir("gobin")
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
goroot := runtime.GOROOT()
|
||||
tg.setenv("GOROOT", goroot)
|
||||
|
||||
// cmd/fix installs into tool
|
||||
tg.run("env", "GOOS")
|
||||
goos := strings.TrimSpace(tg.getStdout())
|
||||
tg.setenv("GOOS", goos)
|
||||
tg.run("env", "GOARCH")
|
||||
goarch := strings.TrimSpace(tg.getStdout())
|
||||
tg.setenv("GOARCH", goarch)
|
||||
fixbin := filepath.Join(goroot, "pkg", "tool", goos+"_"+goarch, "fix") + exeSuffix
|
||||
tg.must(robustio.RemoveAll(fixbin))
|
||||
tg.run("install", "cmd/fix")
|
||||
tg.wantExecutable(fixbin, "did not install cmd/fix to $GOROOT/pkg/tool")
|
||||
tg.must(os.Remove(fixbin))
|
||||
tg.setenv("GOBIN", tg.path("gobin"))
|
||||
tg.run("install", "cmd/fix")
|
||||
tg.wantExecutable(fixbin, "did not install cmd/fix to $GOROOT/pkg/tool with $GOBIN set")
|
||||
tg.unsetenv("GOBIN")
|
||||
|
||||
// gopath program installs into GOBIN
|
||||
tg.tempFile("src/progname/p.go", `package main; func main() {}`)
|
||||
tg.setenv("GOBIN", tg.path("gobin"))
|
||||
tg.run("install", "progname")
|
||||
tg.unsetenv("GOBIN")
|
||||
tg.wantExecutable(tg.path("gobin/progname")+exeSuffix, "did not install progname to $GOBIN/progname")
|
||||
|
||||
// gopath program installs into GOPATH/bin
|
||||
tg.run("install", "progname")
|
||||
tg.wantExecutable(tg.path("bin/progname")+exeSuffix, "did not install progname to $GOPATH/bin/progname")
|
||||
}
|
||||
|
||||
func TestRejectRelativeDotPathInGOPATHCommandLinePackage(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", ".")
|
||||
tg.runFail("build", "testdata/src/go-cmd-test/helloworld.go")
|
||||
tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries")
|
||||
}
|
||||
|
||||
func TestRejectRelativePathsInGOPATH(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
sep := string(filepath.ListSeparator)
|
||||
tg.setenv("GOPATH", sep+filepath.Join(tg.pwd(), "testdata")+sep+".")
|
||||
tg.runFail("build", "go-cmd-test")
|
||||
tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries")
|
||||
}
|
||||
|
||||
func TestRejectRelativePathsInGOPATHCommandLinePackage(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.setenv("GOPATH", "testdata")
|
||||
tg.runFail("build", "testdata/src/go-cmd-test/helloworld.go")
|
||||
tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries")
|
||||
}
|
||||
|
||||
// Issue 21928.
|
||||
func TestRejectBlankPathsInGOPATH(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
sep := string(filepath.ListSeparator)
|
||||
tg.setenv("GOPATH", " "+sep+filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.runFail("build", "go-cmd-test")
|
||||
tg.grepStderr("GOPATH entry is relative", "expected an error message rejecting relative GOPATH entries")
|
||||
}
|
||||
|
||||
// Issue 21928.
|
||||
func TestIgnoreEmptyPathsInGOPATH(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.creatingTemp("testdata/bin/go-cmd-test" + exeSuffix)
|
||||
sep := string(filepath.ListSeparator)
|
||||
tg.setenv("GOPATH", ""+sep+filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.run("install", "go-cmd-test")
|
||||
tg.wantExecutable("testdata/bin/go-cmd-test"+exeSuffix, "go install go-cmd-test did not write to testdata/bin/go-cmd-test")
|
||||
}
|
||||
|
||||
// Issue 4104.
|
||||
func TestGoTestWithPackageListedMultipleTimes(t *testing.T) {
|
||||
tooSlow(t)
|
||||
|
|
@ -2536,57 +2161,6 @@ func TestCoverageDotImport(t *testing.T) {
|
|||
checkCoverage(tg, data)
|
||||
}
|
||||
|
||||
// Check that coverage analysis uses set mode.
|
||||
// Also check that coverage profiles merge correctly.
|
||||
func TestCoverageUsesSetMode(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.creatingTemp("testdata/cover.out")
|
||||
tg.run("test", "-short", "-cover", "encoding/binary", "errors", "-coverprofile=testdata/cover.out")
|
||||
data := tg.getStdout() + tg.getStderr()
|
||||
if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if !bytes.Contains(out, []byte("mode: set")) {
|
||||
t.Error("missing mode: set")
|
||||
}
|
||||
if !bytes.Contains(out, []byte("errors.go")) {
|
||||
t.Error("missing errors.go")
|
||||
}
|
||||
if !bytes.Contains(out, []byte("binary.go")) {
|
||||
t.Error("missing binary.go")
|
||||
}
|
||||
if bytes.Count(out, []byte("mode: set")) != 1 {
|
||||
t.Error("too many mode: set")
|
||||
}
|
||||
}
|
||||
checkCoverage(tg, data)
|
||||
}
|
||||
|
||||
func TestCoverageUsesAtomicModeForRace(t *testing.T) {
|
||||
tooSlow(t)
|
||||
if !canRace {
|
||||
t.Skip("skipping because race detector not supported")
|
||||
}
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.creatingTemp("testdata/cover.out")
|
||||
tg.run("test", "-short", "-race", "-cover", "encoding/binary", "-coverprofile=testdata/cover.out")
|
||||
data := tg.getStdout() + tg.getStderr()
|
||||
if out, err := ioutil.ReadFile("testdata/cover.out"); err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if !bytes.Contains(out, []byte("mode: atomic")) {
|
||||
t.Error("missing mode: atomic")
|
||||
}
|
||||
}
|
||||
checkCoverage(tg, data)
|
||||
}
|
||||
|
||||
func TestCoverageSyncAtomicImport(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo has no cover tool")
|
||||
tooSlow(t)
|
||||
|
|
@ -3081,53 +2655,6 @@ func TestIssue7108(t *testing.T) {
|
|||
tg.runFail("test", "notest")
|
||||
}
|
||||
|
||||
// cmd/go: go test -a foo does not rebuild regexp.
|
||||
func TestIssue6844(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("don't rebuild the standard library in short mode")
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.creatingTemp("deps.test" + exeSuffix)
|
||||
tg.run("test", "-x", "-a", "-c", "testdata/dep_test.go")
|
||||
tg.grepStderr("regexp", "go test -x -a -c testdata/dep-test.go did not rebuild regexp")
|
||||
}
|
||||
|
||||
func TestBuildDashIInstallsDependencies(t *testing.T) {
|
||||
tooSlow(t)
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.tempFile("src/x/y/foo/foo.go", `package foo
|
||||
func F() {}`)
|
||||
tg.tempFile("src/x/y/bar/bar.go", `package bar
|
||||
import "x/y/foo"
|
||||
func F() { foo.F() }`)
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
|
||||
// don't let build -i overwrite runtime
|
||||
tg.wantNotStale("runtime", "", "must be non-stale before build -i")
|
||||
|
||||
checkbar := func(desc string) {
|
||||
tg.run("build", "-v", "-i", "x/y/bar")
|
||||
tg.grepBoth("x/y/foo", "first build -i "+desc+" did not build x/y/foo")
|
||||
tg.run("build", "-v", "-i", "x/y/bar")
|
||||
tg.grepBothNot("x/y/foo", "second build -i "+desc+" built x/y/foo")
|
||||
}
|
||||
checkbar("pkg")
|
||||
|
||||
tg.creatingTemp("bar" + exeSuffix)
|
||||
tg.sleep()
|
||||
tg.tempFile("src/x/y/foo/foo.go", `package foo
|
||||
func F() { F() }`)
|
||||
tg.tempFile("src/x/y/bar/bar.go", `package main
|
||||
import "x/y/foo"
|
||||
func main() { foo.F() }`)
|
||||
checkbar("cmd")
|
||||
}
|
||||
|
||||
func TestGoBuildTestOnly(t *testing.T) {
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
|
|
@ -3412,95 +2939,6 @@ func TestGoGetDotSlashDownload(t *testing.T) {
|
|||
tg.run("get", "./pprof_mac_fix")
|
||||
}
|
||||
|
||||
// Test that you cannot import a main package.
|
||||
// See golang.org/issue/4210 and golang.org/issue/17475.
|
||||
func TestImportMain(t *testing.T) {
|
||||
tooSlow(t)
|
||||
|
||||
tg := testgo(t)
|
||||
tg.parallel()
|
||||
defer tg.cleanup()
|
||||
|
||||
// Importing package main from that package main's test should work.
|
||||
tg.tempFile("src/x/main.go", `package main
|
||||
var X int
|
||||
func main() {}`)
|
||||
tg.tempFile("src/x/main_test.go", `package main_test
|
||||
import xmain "x"
|
||||
import "testing"
|
||||
var _ = xmain.X
|
||||
func TestFoo(t *testing.T) {}
|
||||
`)
|
||||
tg.setenv("GOPATH", tg.path("."))
|
||||
tg.creatingTemp("x" + exeSuffix)
|
||||
tg.run("build", "x")
|
||||
tg.run("test", "x")
|
||||
|
||||
// Importing package main from another package should fail.
|
||||
tg.tempFile("src/p1/p.go", `package p1
|
||||
import xmain "x"
|
||||
var _ = xmain.X
|
||||
`)
|
||||
tg.runFail("build", "p1")
|
||||
tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
|
||||
|
||||
// ... even in that package's test.
|
||||
tg.tempFile("src/p2/p.go", `package p2
|
||||
`)
|
||||
tg.tempFile("src/p2/p_test.go", `package p2
|
||||
import xmain "x"
|
||||
import "testing"
|
||||
var _ = xmain.X
|
||||
func TestFoo(t *testing.T) {}
|
||||
`)
|
||||
tg.run("build", "p2")
|
||||
tg.runFail("test", "p2")
|
||||
tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
|
||||
|
||||
// ... even if that package's test is an xtest.
|
||||
tg.tempFile("src/p3/p.go", `package p
|
||||
`)
|
||||
tg.tempFile("src/p3/p_test.go", `package p_test
|
||||
import xmain "x"
|
||||
import "testing"
|
||||
var _ = xmain.X
|
||||
func TestFoo(t *testing.T) {}
|
||||
`)
|
||||
tg.run("build", "p3")
|
||||
tg.runFail("test", "p3")
|
||||
tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
|
||||
|
||||
// ... even if that package is a package main
|
||||
tg.tempFile("src/p4/p.go", `package main
|
||||
func main() {}
|
||||
`)
|
||||
tg.tempFile("src/p4/p_test.go", `package main
|
||||
import xmain "x"
|
||||
import "testing"
|
||||
var _ = xmain.X
|
||||
func TestFoo(t *testing.T) {}
|
||||
`)
|
||||
tg.creatingTemp("p4" + exeSuffix)
|
||||
tg.run("build", "p4")
|
||||
tg.runFail("test", "p4")
|
||||
tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
|
||||
|
||||
// ... even if that package is a package main using an xtest.
|
||||
tg.tempFile("src/p5/p.go", `package main
|
||||
func main() {}
|
||||
`)
|
||||
tg.tempFile("src/p5/p_test.go", `package main_test
|
||||
import xmain "x"
|
||||
import "testing"
|
||||
var _ = xmain.X
|
||||
func TestFoo(t *testing.T) {}
|
||||
`)
|
||||
tg.creatingTemp("p5" + exeSuffix)
|
||||
tg.run("build", "p5")
|
||||
tg.runFail("test", "p5")
|
||||
tg.grepStderr("import \"x\" is a program, not an importable package", "did not diagnose package main")
|
||||
}
|
||||
|
||||
// Test that you cannot use a local import in a package
|
||||
// accessed by a non-local import (found in a GOPATH/GOROOT).
|
||||
// See golang.org/issue/17475.
|
||||
|
|
@ -3811,7 +3249,17 @@ func TestGoTestRaceInstallCgo(t *testing.T) {
|
|||
cgo := strings.TrimSpace(tg.stdout.String())
|
||||
old, err := os.Stat(cgo)
|
||||
tg.must(err)
|
||||
tg.run("test", "-race", "-i", "runtime/race")
|
||||
|
||||
// For this test, we don't actually care whether 'go test -race -i' succeeds.
|
||||
// It may fail, for example, if GOROOT was installed from source as root and
|
||||
// is now read-only.
|
||||
// We only care that — regardless of whether it succeeds — it does not
|
||||
// overwrite cmd/cgo.
|
||||
runArgs := []string{"test", "-race", "-i", "runtime/race"}
|
||||
if status := tg.doRun(runArgs); status != nil {
|
||||
tg.t.Logf("go %v failure ignored: %v", runArgs, status)
|
||||
}
|
||||
|
||||
new, err := os.Stat(cgo)
|
||||
tg.must(err)
|
||||
if !new.ModTime().Equal(old.ModTime()) {
|
||||
|
|
@ -4789,36 +4237,6 @@ func TestNeedVersion(t *testing.T) {
|
|||
tg.grepStderr("compile", "does not match go tool version")
|
||||
}
|
||||
|
||||
// Test that user can override default code generation flags.
|
||||
func TestUserOverrideFlags(t *testing.T) {
|
||||
skipIfGccgo(t, "gccgo does not use -gcflags")
|
||||
if !canCgo {
|
||||
t.Skip("skipping because cgo not enabled")
|
||||
}
|
||||
if runtime.GOOS != "linux" {
|
||||
// We are testing platform-independent code, so it's
|
||||
// OK to skip cases that work differently.
|
||||
t.Skipf("skipping on %s because test only works if c-archive implies -shared", runtime.GOOS)
|
||||
}
|
||||
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
// Don't call tg.parallel, as creating override.h and override.a may
|
||||
// confuse other tests.
|
||||
tg.tempFile("override.go", `package main
|
||||
|
||||
import "C"
|
||||
|
||||
//export GoFunc
|
||||
func GoFunc() {}
|
||||
|
||||
func main() {}`)
|
||||
tg.creatingTemp("override.a")
|
||||
tg.creatingTemp("override.h")
|
||||
tg.run("build", "-x", "-buildmode=c-archive", "-gcflags=all=-shared=false", tg.path("override.go"))
|
||||
tg.grepStderr("compile .*-shared .*-shared=false", "user can not override code generation flag")
|
||||
}
|
||||
|
||||
func TestCgoFlagContainsSpace(t *testing.T) {
|
||||
tooSlow(t)
|
||||
if !canCgo {
|
||||
|
|
@ -5403,122 +4821,6 @@ func TestTestCache(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestTestCacheInputs(t *testing.T) {
|
||||
tooSlow(t)
|
||||
|
||||
if strings.Contains(os.Getenv("GODEBUG"), "gocacheverify") {
|
||||
t.Skip("GODEBUG gocacheverify")
|
||||
}
|
||||
tg := testgo(t)
|
||||
defer tg.cleanup()
|
||||
tg.parallel()
|
||||
tg.makeTempdir()
|
||||
tg.setenv("GOPATH", filepath.Join(tg.pwd(), "testdata"))
|
||||
tg.setenv("GOCACHE", tg.path("cache"))
|
||||
|
||||
defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"))
|
||||
defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"))
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("x"), 0644))
|
||||
old := time.Now().Add(-1 * time.Minute)
|
||||
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old, old))
|
||||
info, err := os.Stat(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Logf("file.txt: old=%v, info.ModTime=%v", old, info.ModTime()) // help debug when Chtimes lies about succeeding
|
||||
tg.setenv("TESTKEY", "x")
|
||||
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), []byte("#!/bin/sh\nexit 0\n"), 0755))
|
||||
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), old, old))
|
||||
|
||||
tg.run("test", "testcache")
|
||||
tg.run("test", "testcache")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
tg.setenv("TESTKEY", "y")
|
||||
tg.run("test", "testcache")
|
||||
tg.grepStdoutNot(`\(cached\)`, "did not notice env var change")
|
||||
tg.run("test", "testcache")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
tg.run("test", "testcache", "-run=FileSize")
|
||||
tg.run("test", "testcache", "-run=FileSize")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("xxx"), 0644))
|
||||
tg.run("test", "testcache", "-run=FileSize")
|
||||
tg.grepStdoutNot(`\(cached\)`, "did not notice file size change")
|
||||
tg.run("test", "testcache", "-run=FileSize")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
tg.run("test", "testcache", "-run=Chdir")
|
||||
tg.run("test", "testcache", "-run=Chdir")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("xxxxx"), 0644))
|
||||
tg.run("test", "testcache", "-run=Chdir")
|
||||
tg.grepStdoutNot(`\(cached\)`, "did not notice file size change")
|
||||
tg.run("test", "testcache", "-run=Chdir")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old, old))
|
||||
tg.run("test", "testcache", "-run=FileContent")
|
||||
tg.run("test", "testcache", "-run=FileContent")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), []byte("yyy"), 0644))
|
||||
old2 := old.Add(10 * time.Second)
|
||||
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt"), old2, old2))
|
||||
tg.run("test", "testcache", "-run=FileContent")
|
||||
tg.grepStdoutNot(`\(cached\)`, "did not notice file content change")
|
||||
tg.run("test", "testcache", "-run=FileContent")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
tg.run("test", "testcache", "-run=DirList")
|
||||
tg.run("test", "testcache", "-run=DirList")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
tg.must(os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/file.txt")))
|
||||
tg.run("test", "testcache", "-run=DirList")
|
||||
tg.grepStdoutNot(`\(cached\)`, "did not notice directory change")
|
||||
tg.run("test", "testcache", "-run=DirList")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
tg.tempFile("file.txt", "")
|
||||
tg.must(ioutil.WriteFile(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"), []byte(`package testcache
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExternalFile(t *testing.T) {
|
||||
os.Open(`+fmt.Sprintf("%q", tg.path("file.txt"))+`)
|
||||
_, err := os.Stat(`+fmt.Sprintf("%q", tg.path("file.txt"))+`)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
`), 0666))
|
||||
defer os.Remove(filepath.Join(tg.pwd(), "testdata/src/testcache/testcachetmp_test.go"))
|
||||
tg.run("test", "testcache", "-run=ExternalFile")
|
||||
tg.run("test", "testcache", "-run=ExternalFile")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
tg.must(os.Remove(filepath.Join(tg.tempdir, "file.txt")))
|
||||
tg.run("test", "testcache", "-run=ExternalFile")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
|
||||
switch runtime.GOOS {
|
||||
case "plan9", "windows":
|
||||
// no shell scripts
|
||||
default:
|
||||
tg.run("test", "testcache", "-run=Exec")
|
||||
tg.run("test", "testcache", "-run=Exec")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
tg.must(os.Chtimes(filepath.Join(tg.pwd(), "testdata/src/testcache/script.sh"), old2, old2))
|
||||
tg.run("test", "testcache", "-run=Exec")
|
||||
tg.grepStdoutNot(`\(cached\)`, "did not notice script change")
|
||||
tg.run("test", "testcache", "-run=Exec")
|
||||
tg.grepStdout(`\(cached\)`, "did not cache")
|
||||
}
|
||||
}
|
||||
|
||||
func TestTestVet(t *testing.T) {
|
||||
tooSlow(t)
|
||||
tg := testgo(t)
|
||||
|
|
|
|||
|
|
@ -1584,7 +1584,10 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
|||
p.Target = ""
|
||||
} else {
|
||||
p.Target = p.Internal.Build.PkgObj
|
||||
if cfg.BuildLinkshared {
|
||||
if cfg.BuildLinkshared && p.Target != "" {
|
||||
// TODO(bcmills): The reliance on p.Target implies that -linkshared does
|
||||
// not work for any package that lacks a Target — such as a non-main
|
||||
// package in module mode. We should probably fix that.
|
||||
shlibnamefile := p.Target[:len(p.Target)-2] + ".shlibname"
|
||||
shlib, err := ioutil.ReadFile(shlibnamefile)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import (
|
|||
)
|
||||
|
||||
var cmdDownload = &base.Command{
|
||||
UsageLine: "go mod download [-json] [modules]",
|
||||
UsageLine: "go mod download [-x] [-json] [modules]",
|
||||
Short: "download modules to local cache",
|
||||
Long: `
|
||||
Download downloads the named modules, which can be module patterns selecting
|
||||
|
|
@ -47,6 +47,8 @@ corresponding to this Go struct:
|
|||
GoModSum string // checksum for go.mod (as in go.sum)
|
||||
}
|
||||
|
||||
The -x flag causes download to print the commands download executes.
|
||||
|
||||
See 'go help modules' for more about module queries.
|
||||
`,
|
||||
}
|
||||
|
|
@ -56,6 +58,8 @@ var downloadJSON = cmdDownload.Flag.Bool("json", false, "")
|
|||
func init() {
|
||||
cmdDownload.Run = runDownload // break init cycle
|
||||
|
||||
// TODO(jayconrod): https://golang.org/issue/35849 Apply -x to other 'go mod' commands.
|
||||
cmdDownload.Flag.BoolVar(&cfg.BuildX, "x", false, "")
|
||||
work.AddModCommonFlags(cmdDownload)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -458,7 +458,9 @@ func runGet(cmd *base.Command, args []string) {
|
|||
modOnly := make(map[string]*query)
|
||||
for _, q := range queries {
|
||||
if q.m.Version == "none" {
|
||||
modOnlyMu.Lock()
|
||||
modOnly[q.m.Path] = q
|
||||
modOnlyMu.Unlock()
|
||||
continue
|
||||
}
|
||||
if q.path == q.m.Path {
|
||||
|
|
|
|||
|
|
@ -57,8 +57,8 @@ func listModules(args []string, listVersions bool) []*modinfo.ModulePublic {
|
|||
if search.IsRelativePath(arg) {
|
||||
base.Fatalf("go: cannot use relative path %s to specify module", arg)
|
||||
}
|
||||
if !HasModRoot() && arg == "all" {
|
||||
base.Fatalf(`go: cannot match "all": working directory is not part of a module`)
|
||||
if !HasModRoot() && (arg == "all" || strings.Contains(arg, "...")) {
|
||||
base.Fatalf("go: cannot match %q: working directory is not part of a module", arg)
|
||||
}
|
||||
if i := strings.Index(arg, "@"); i >= 0 {
|
||||
path := arg[:i]
|
||||
|
|
|
|||
|
|
@ -1036,7 +1036,7 @@ func (b *Builder) vet(a *Action) error {
|
|||
// There's too much unsafe.Pointer code
|
||||
// that vet doesn't like in low-level packages
|
||||
// like runtime, sync, and reflect.
|
||||
vetFlags = []string{"-unsafeptr=false"}
|
||||
vetFlags = append(vetFlags, string("-unsafeptr=false"))
|
||||
}
|
||||
|
||||
// Note: We could decide that vet should compute export data for
|
||||
|
|
|
|||
|
|
@ -86,7 +86,11 @@ func instrumentInit() {
|
|||
func buildModeInit() {
|
||||
gccgo := cfg.BuildToolchainName == "gccgo"
|
||||
var codegenArg string
|
||||
platform := cfg.Goos + "/" + cfg.Goarch
|
||||
|
||||
// Configure the build mode first, then verify that it is supported.
|
||||
// That way, if the flag is completely bogus we will prefer to error out with
|
||||
// "-buildmode=%s not supported" instead of naming the specific platform.
|
||||
|
||||
switch cfg.BuildBuildmode {
|
||||
case "archive":
|
||||
pkgsFilter = pkgsNotMain
|
||||
|
|
@ -95,20 +99,18 @@ func buildModeInit() {
|
|||
if gccgo {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
switch platform {
|
||||
case "darwin/arm", "darwin/arm64":
|
||||
codegenArg = "-shared"
|
||||
default:
|
||||
switch cfg.Goos {
|
||||
case "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris":
|
||||
if platform == "linux/ppc64" {
|
||||
base.Fatalf("-buildmode=c-archive not supported on %s\n", platform)
|
||||
}
|
||||
// Use -shared so that the result is
|
||||
// suitable for inclusion in a PIE or
|
||||
// shared library.
|
||||
switch cfg.Goos {
|
||||
case "darwin":
|
||||
switch cfg.Goarch {
|
||||
case "arm", "arm64":
|
||||
codegenArg = "-shared"
|
||||
}
|
||||
|
||||
case "dragonfly", "freebsd", "illumos", "linux", "netbsd", "openbsd", "solaris":
|
||||
// Use -shared so that the result is
|
||||
// suitable for inclusion in a PIE or
|
||||
// shared library.
|
||||
codegenArg = "-shared"
|
||||
}
|
||||
}
|
||||
cfg.ExeSuffix = ".a"
|
||||
|
|
@ -118,27 +120,25 @@ func buildModeInit() {
|
|||
if gccgo {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
switch platform {
|
||||
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"freebsd/amd64":
|
||||
switch cfg.Goos {
|
||||
case "linux", "android", "freebsd":
|
||||
codegenArg = "-shared"
|
||||
case "darwin/amd64", "darwin/386":
|
||||
case "windows/amd64", "windows/386":
|
||||
case "windows":
|
||||
// Do not add usual .exe suffix to the .dll file.
|
||||
cfg.ExeSuffix = ""
|
||||
default:
|
||||
base.Fatalf("-buildmode=c-shared not supported on %s\n", platform)
|
||||
}
|
||||
}
|
||||
ldBuildmode = "c-shared"
|
||||
case "default":
|
||||
switch platform {
|
||||
case "android/arm", "android/arm64", "android/amd64", "android/386":
|
||||
switch cfg.Goos {
|
||||
case "android":
|
||||
codegenArg = "-shared"
|
||||
ldBuildmode = "pie"
|
||||
case "darwin/arm", "darwin/arm64":
|
||||
codegenArg = "-shared"
|
||||
case "darwin":
|
||||
switch cfg.Goarch {
|
||||
case "arm", "arm64":
|
||||
codegenArg = "-shared"
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
ldBuildmode = "exe"
|
||||
|
|
@ -161,18 +161,8 @@ func buildModeInit() {
|
|||
}
|
||||
if gccgo {
|
||||
codegenArg = "-fPIE"
|
||||
} else {
|
||||
switch platform {
|
||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"freebsd/amd64":
|
||||
codegenArg = "-shared"
|
||||
case "darwin/amd64":
|
||||
codegenArg = "-shared"
|
||||
case "aix/ppc64":
|
||||
default:
|
||||
base.Fatalf("-buildmode=pie not supported on %s\n", platform)
|
||||
}
|
||||
} else if cfg.Goos != "aix" {
|
||||
codegenArg = "-shared"
|
||||
}
|
||||
ldBuildmode = "pie"
|
||||
case "shared":
|
||||
|
|
@ -180,11 +170,6 @@ func buildModeInit() {
|
|||
if gccgo {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
switch platform {
|
||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
|
||||
default:
|
||||
base.Fatalf("-buildmode=shared not supported on %s\n", platform)
|
||||
}
|
||||
codegenArg = "-dynlink"
|
||||
}
|
||||
if cfg.BuildO != "" {
|
||||
|
|
@ -196,14 +181,6 @@ func buildModeInit() {
|
|||
if gccgo {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
switch platform {
|
||||
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386":
|
||||
case "darwin/amd64":
|
||||
case "freebsd/amd64":
|
||||
default:
|
||||
base.Fatalf("-buildmode=plugin not supported on %s\n", platform)
|
||||
}
|
||||
codegenArg = "-dynlink"
|
||||
}
|
||||
cfg.ExeSuffix = ".so"
|
||||
|
|
@ -211,16 +188,19 @@ func buildModeInit() {
|
|||
default:
|
||||
base.Fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
|
||||
}
|
||||
|
||||
if !sys.BuildModeSupported(cfg.BuildToolchainName, cfg.BuildBuildmode, cfg.Goos, cfg.Goarch) {
|
||||
base.Fatalf("-buildmode=%s not supported on %s/%s\n", cfg.BuildBuildmode, cfg.Goos, cfg.Goarch)
|
||||
}
|
||||
|
||||
if cfg.BuildLinkshared {
|
||||
if !sys.BuildModeSupported(cfg.BuildToolchainName, "shared", cfg.Goos, cfg.Goarch) {
|
||||
base.Fatalf("-linkshared not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
|
||||
}
|
||||
if gccgo {
|
||||
codegenArg = "-fPIC"
|
||||
} else {
|
||||
switch platform {
|
||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
|
||||
forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1")
|
||||
default:
|
||||
base.Fatalf("-linkshared not supported on %s\n", platform)
|
||||
}
|
||||
forcedAsmflags = append(forcedAsmflags, "-D=GOBUILDMODE_shared=1")
|
||||
codegenArg = "-dynlink"
|
||||
forcedGcflags = append(forcedGcflags, "-linkshared")
|
||||
// TODO(mwhudson): remove -w when that gets fixed in linker.
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import (
|
|||
"cmd/go/internal/robustio"
|
||||
"cmd/go/internal/txtar"
|
||||
"cmd/go/internal/work"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
// TestScript runs the tests in testdata/script/*.txt.
|
||||
|
|
@ -303,6 +304,11 @@ Script:
|
|||
}
|
||||
break
|
||||
}
|
||||
if strings.HasPrefix(cond.tag, "buildmode:") {
|
||||
value := strings.TrimPrefix(cond.tag, "buildmode:")
|
||||
ok = sys.BuildModeSupported(runtime.Compiler, value, runtime.GOOS, runtime.GOARCH)
|
||||
break
|
||||
}
|
||||
if !imports.KnownArch[cond.tag] && !imports.KnownOS[cond.tag] && cond.tag != "gc" && cond.tag != "gccgo" {
|
||||
ts.fatalf("unknown condition %q", cond.tag)
|
||||
}
|
||||
|
|
@ -580,26 +586,31 @@ func (ts *testScript) cmdEnv(neg bool, args []string) {
|
|||
args = args[1:]
|
||||
}
|
||||
|
||||
var out strings.Builder
|
||||
if len(args) == 0 {
|
||||
printed := make(map[string]bool) // env list can have duplicates; only print effective value (from envMap) once
|
||||
for _, kv := range ts.env {
|
||||
k := kv[:strings.Index(kv, "=")]
|
||||
if !printed[k] {
|
||||
fmt.Fprintf(&ts.log, "%s=%s\n", k, ts.envMap[k])
|
||||
fmt.Fprintf(&out, "%s=%s\n", k, ts.envMap[k])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, env := range args {
|
||||
i := strings.Index(env, "=")
|
||||
if i < 0 {
|
||||
// Display value instead of setting it.
|
||||
fmt.Fprintf(&ts.log, "%s=%s\n", env, ts.envMap[env])
|
||||
continue
|
||||
} else {
|
||||
for _, env := range args {
|
||||
i := strings.Index(env, "=")
|
||||
if i < 0 {
|
||||
// Display value instead of setting it.
|
||||
fmt.Fprintf(&out, "%s=%s\n", env, ts.envMap[env])
|
||||
continue
|
||||
}
|
||||
key, val := env[:i], conv(env[i+1:])
|
||||
ts.env = append(ts.env, key+"="+val)
|
||||
ts.envMap[key] = val
|
||||
}
|
||||
key, val := env[:i], conv(env[i+1:])
|
||||
ts.env = append(ts.env, key+"="+val)
|
||||
ts.envMap[key] = val
|
||||
}
|
||||
if out.Len() > 0 || len(args) > 0 {
|
||||
ts.stdout = out.String()
|
||||
ts.log.WriteString(out.String())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
7
src/cmd/go/testdata/dep_test.go
vendored
7
src/cmd/go/testdata/dep_test.go
vendored
|
|
@ -1,7 +0,0 @@
|
|||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package deps
|
||||
|
||||
import _ "testing"
|
||||
7
src/cmd/go/testdata/local/easy.go
vendored
7
src/cmd/go/testdata/local/easy.go
vendored
|
|
@ -1,7 +0,0 @@
|
|||
package main
|
||||
|
||||
import "./easysub"
|
||||
|
||||
func main() {
|
||||
easysub.Hello()
|
||||
}
|
||||
7
src/cmd/go/testdata/local/easysub/easysub.go
vendored
7
src/cmd/go/testdata/local/easysub/easysub.go
vendored
|
|
@ -1,7 +0,0 @@
|
|||
package easysub
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Hello() {
|
||||
fmt.Println("easysub.Hello")
|
||||
}
|
||||
9
src/cmd/go/testdata/local/easysub/main.go
vendored
9
src/cmd/go/testdata/local/easysub/main.go
vendored
|
|
@ -1,9 +0,0 @@
|
|||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import "."
|
||||
|
||||
func main() {
|
||||
easysub.Hello()
|
||||
}
|
||||
7
src/cmd/go/testdata/local/hard.go
vendored
7
src/cmd/go/testdata/local/hard.go
vendored
|
|
@ -1,7 +0,0 @@
|
|||
package main
|
||||
|
||||
import "./sub"
|
||||
|
||||
func main() {
|
||||
sub.Hello()
|
||||
}
|
||||
12
src/cmd/go/testdata/local/sub/sub.go
vendored
12
src/cmd/go/testdata/local/sub/sub.go
vendored
|
|
@ -1,12 +0,0 @@
|
|||
package sub
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
subsub "./sub"
|
||||
)
|
||||
|
||||
func Hello() {
|
||||
fmt.Println("sub.Hello")
|
||||
subsub.Hello()
|
||||
}
|
||||
7
src/cmd/go/testdata/local/sub/sub/subsub.go
vendored
7
src/cmd/go/testdata/local/sub/sub/subsub.go
vendored
|
|
@ -1,7 +0,0 @@
|
|||
package subsub
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Hello() {
|
||||
fmt.Println("subsub.Hello")
|
||||
}
|
||||
7
src/cmd/go/testdata/script/README
vendored
7
src/cmd/go/testdata/script/README
vendored
|
|
@ -38,6 +38,7 @@ Scripts also have access to these other environment variables:
|
|||
TMPDIR=$WORK/tmp
|
||||
devnull=<value of os.DevNull>
|
||||
goversion=<current Go version; for example, 1.12>
|
||||
:=<OS-specific path list separator>
|
||||
|
||||
The scripts supporting files are unpacked relative to $GOPATH/src (aka $WORK/gopath/src)
|
||||
and then the script begins execution in that directory as well. Thus the example above runs
|
||||
|
|
@ -78,6 +79,7 @@ should only run when the condition is satisfied. The available conditions are:
|
|||
- [symlink] for testenv.HasSymlink()
|
||||
- [exec:prog] for whether prog is available for execution (found by exec.LookPath)
|
||||
- [GODEBUG:value] for whether value is one of the comma-separated entries in the GODEBUG variable
|
||||
- [buildmode:value] for whether -buildmode=value is supported
|
||||
|
||||
A condition can be negated: [!short] means to run the rest of the line
|
||||
when testing.Short() is false. Multiple conditions may be given for a single
|
||||
|
|
@ -114,7 +116,8 @@ The commands are:
|
|||
from the most recent exec or go command.
|
||||
|
||||
- env [-r] [key=value...]
|
||||
With no arguments, print the environment (useful for debugging).
|
||||
With no arguments, print the environment to stdout
|
||||
(useful for debugging and for verifying initial state).
|
||||
Otherwise add the listed key=value pairs to the environment.
|
||||
The -r flag causes the values to be escaped using regexp.QuoteMeta
|
||||
before being recorded.
|
||||
|
|
@ -163,7 +166,7 @@ The commands are:
|
|||
|
||||
- [!] stdout [-count=N] pattern
|
||||
Apply the grep command (see above) to the standard output
|
||||
from the most recent exec, go, or wait command.
|
||||
from the most recent exec, go, wait, or env command.
|
||||
|
||||
- stop [message]
|
||||
Stop the test early (marking it as passing), including the message if given.
|
||||
|
|
|
|||
21
src/cmd/go/testdata/script/build_gcflags.txt
vendored
Normal file
21
src/cmd/go/testdata/script/build_gcflags.txt
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Test that the user can override default code generation flags.
|
||||
|
||||
[gccgo] skip # gccgo does not use -gcflags
|
||||
[!cgo] skip
|
||||
[!linux] skip # test only works if c-archive implies -shared
|
||||
[short] skip
|
||||
|
||||
go build -x -buildmode=c-archive -gcflags=all=-shared=false ./override.go
|
||||
stderr '^.*/compile (.* )?-shared (.* )?-shared=false'
|
||||
|
||||
-- override.go --
|
||||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
//export GoFunc
|
||||
func GoFunc() {}
|
||||
|
||||
func main() {}
|
||||
41
src/cmd/go/testdata/script/build_i.txt
vendored
Normal file
41
src/cmd/go/testdata/script/build_i.txt
vendored
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Test that 'go build -i' installs dependencies of the requested package.
|
||||
|
||||
[short] skip
|
||||
|
||||
# Since we are checking installation of dependencies, use a clean cache
|
||||
# to ensure that multiple runs of the test do not interfere.
|
||||
env GOCACHE=$WORK/cache
|
||||
|
||||
# The initial 'go build -i' for bar should install its dependency foo.
|
||||
|
||||
go build -v -i x/y/bar
|
||||
stderr 'x/y/foo' # should be rebuilt
|
||||
go build -v -i x/y/bar
|
||||
! stderr 'x/y/foo' # should already be installed
|
||||
|
||||
# After modifying the source files, both packages should be rebuild.
|
||||
|
||||
cp x/y/foo/foo.go.next x/y/foo/foo.go
|
||||
cp x/y/bar/bar.go.next x/y/bar/bar.go
|
||||
|
||||
go build -v -i x/y/bar
|
||||
stderr 'x/y/foo' # should be rebuilt
|
||||
go build -v -i x/y/bar
|
||||
! stderr 'x/y/foo' # should already be installed
|
||||
|
||||
-- x/y/foo/foo.go --
|
||||
package foo
|
||||
func F() {}
|
||||
-- x/y/bar/bar.go --
|
||||
package bar
|
||||
import "x/y/foo"
|
||||
func F() { foo.F() }
|
||||
-- x/y/foo/foo.go.next --
|
||||
package foo
|
||||
func F() { F() }
|
||||
-- x/y/bar/bar.go.next --
|
||||
package main
|
||||
import "x/y/foo"
|
||||
func main() { foo.F() }
|
||||
119
src/cmd/go/testdata/script/build_trimpath.txt
vendored
119
src/cmd/go/testdata/script/build_trimpath.txt
vendored
|
|
@ -1,64 +1,92 @@
|
|||
[short] skip
|
||||
env GO111MODULE=on
|
||||
|
||||
# A binary built without -trimpath should contain the current workspace
|
||||
# Set up two identical directories that can be used as GOPATH.
|
||||
env GO111MODULE=on
|
||||
mkdir $WORK/a/src/paths $WORK/b/src/paths
|
||||
cp paths.go $WORK/a/src/paths
|
||||
cp paths.go $WORK/b/src/paths
|
||||
cp go.mod $WORK/a/src/paths/
|
||||
cp go.mod $WORK/b/src/paths/
|
||||
|
||||
|
||||
# A binary built without -trimpath should contain the module root dir
|
||||
# and GOROOT for debugging and stack traces.
|
||||
cd a
|
||||
go build -o $WORK/paths-a.exe paths.go
|
||||
exec $WORK/paths-a.exe $WORK/paths-a.exe
|
||||
stdout 'binary contains GOPATH: true'
|
||||
cd $WORK/a/src/paths
|
||||
go build -o $WORK/paths-dbg.exe .
|
||||
exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
|
||||
stdout 'binary contains module root: true'
|
||||
stdout 'binary contains GOROOT: true'
|
||||
|
||||
# A binary built with -trimpath should not contain the current workspace
|
||||
# or GOROOT.
|
||||
go build -trimpath -o $WORK/paths-a.exe paths.go
|
||||
go build -trimpath -o $WORK/paths-a.exe .
|
||||
exec $WORK/paths-a.exe $WORK/paths-a.exe
|
||||
stdout 'binary contains GOPATH: false'
|
||||
stdout 'binary contains module root: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
|
||||
# A binary from an external module built with -trimpath should not contain
|
||||
# the current workspace or GOROOT.
|
||||
cd $WORK
|
||||
go get -trimpath rsc.io/fortune
|
||||
exec $WORK/paths-a.exe $GOPATH/bin/fortune$GOEXE
|
||||
stdout 'binary contains GOPATH: false'
|
||||
stdout 'binary contains module root: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
go mod edit -droprequire rsc.io/fortune
|
||||
|
||||
# Two binaries built from identical packages in different directories
|
||||
# should be identical.
|
||||
# TODO(golang.org/issue/35435): at the moment, they are not.
|
||||
#mkdir $GOPATH/src/b
|
||||
#cp $GOPATH/src/a/go.mod $GOPATH/src/b/go.mod
|
||||
#cp $GOPATH/src/a/paths.go $GOPATH/src/b/paths.go
|
||||
#cd $GOPATH/src/b
|
||||
#go build -trimpath -o $WORK/paths-b.exe .
|
||||
#cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
|
||||
cd $WORK/b/src/paths
|
||||
go build -trimpath -o $WORK/paths-b.exe
|
||||
cmp -q $WORK/paths-a.exe $WORK/paths-b.exe
|
||||
|
||||
|
||||
# Same sequence of tests but in GOPATH mode.
|
||||
# A binary built without -trimpath should contain GOPATH and GOROOT.
|
||||
env GO111MODULE=off
|
||||
cd $WORK
|
||||
env GOPATH=$WORK/a
|
||||
go build -o paths-dbg.exe paths
|
||||
exec ./paths-dbg.exe paths-dbg.exe
|
||||
stdout 'binary contains GOPATH: true'
|
||||
stdout 'binary contains GOROOT: true'
|
||||
|
||||
# A binary built with -trimpath should not contain GOPATH or GOROOT.
|
||||
go build -trimpath -o paths-a.exe paths
|
||||
exec ./paths-a.exe paths-a.exe
|
||||
stdout 'binary contains GOPATH: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
|
||||
# Two binaries built from identical packages in different GOPATH roots
|
||||
# should be identical.
|
||||
env GOPATH=$WORK/b
|
||||
go build -trimpath -o paths-b.exe paths
|
||||
cmp -q paths-a.exe paths-b.exe
|
||||
|
||||
|
||||
# Same sequence of tests but with gccgo.
|
||||
# gccgo does not support builds in module mode.
|
||||
[!exec:gccgo] stop
|
||||
env GOPATH=$WORK/a
|
||||
|
||||
# A binary built with gccgo without -trimpath should contain the current
|
||||
# GOPATH and GOROOT.
|
||||
env GO111MODULE=off # The current released gccgo does not support builds in module mode.
|
||||
cd $GOPATH/src/a
|
||||
go build -compiler=gccgo -o $WORK/gccgo-paths-a.exe .
|
||||
exec $WORK/gccgo-paths-a.exe $WORK/gccgo-paths-a.exe
|
||||
go build -compiler=gccgo -o paths-dbg.exe paths
|
||||
exec ./paths-dbg.exe paths-dbg.exe
|
||||
stdout 'binary contains GOPATH: true'
|
||||
stdout 'binary contains GOROOT: false' # gccgo doesn't load std from GOROOT.
|
||||
|
||||
# A binary built with gccgo with -trimpath should not contain GOPATH or GOROOT.
|
||||
go build -compiler=gccgo -trimpath -o $WORK/gccgo-paths-b.exe .
|
||||
exec $WORK/gccgo-paths-a.exe $WORK/gccgo-paths-b.exe
|
||||
go build -compiler=gccgo -trimpath -o paths-a.exe paths
|
||||
exec ./paths-a.exe paths-a.exe
|
||||
stdout 'binary contains GOPATH: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
|
||||
# Two binaries built from identical packages in different directories
|
||||
# should be identical.
|
||||
# TODO(golang.org/issue/35435): at the moment, they are not.
|
||||
#cd ../b
|
||||
#go build -compiler=gccgo -trimpath -o $WORK/gccgo-paths-b.exe .
|
||||
#cmp -q $WORK/gccgo-paths-a.exe $WORK/gccgo-paths-b.exe
|
||||
env GOPATH=$WORK/b
|
||||
go build -compiler=gccgo -trimpath -o paths-b.exe paths
|
||||
cmp -q paths-a.exe paths-b.exe
|
||||
|
||||
-- $GOPATH/src/a/paths.go --
|
||||
-- paths.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
@ -67,7 +95,9 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
@ -77,17 +107,26 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
gopath := []byte(filepath.ToSlash(os.Getenv("GOPATH")))
|
||||
if len(gopath) == 0 {
|
||||
log.Fatal("GOPATH not set")
|
||||
if os.Getenv("GO111MODULE") == "on" {
|
||||
out, err := exec.Command("go", "env", "GOMOD").Output()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
modRoot := filepath.Dir(strings.TrimSpace(string(out)))
|
||||
check(data, "module root", modRoot)
|
||||
} else {
|
||||
check(data, "GOPATH", os.Getenv("GOPATH"))
|
||||
}
|
||||
fmt.Printf("binary contains GOPATH: %v\n", bytes.Contains(data, gopath))
|
||||
|
||||
goroot := []byte(filepath.ToSlash(os.Getenv("GOROOT")))
|
||||
if len(goroot) == 0 {
|
||||
log.Fatal("GOROOT not set")
|
||||
}
|
||||
fmt.Printf("binary contains GOROOT: %v\n", bytes.Contains(data, goroot))
|
||||
check(data, "GOROOT", os.Getenv("GOROOT"))
|
||||
}
|
||||
-- $GOPATH/src/a/go.mod --
|
||||
module example.com/a
|
||||
|
||||
func check(data []byte, desc, dir string) {
|
||||
containsDir := bytes.Contains(data, []byte(dir))
|
||||
containsSlashDir := bytes.Contains(data, []byte(filepath.ToSlash(dir)))
|
||||
fmt.Printf("binary contains %s: %v\n", desc, containsDir || containsSlashDir)
|
||||
}
|
||||
|
||||
-- go.mod --
|
||||
module paths
|
||||
|
||||
go 1.14
|
||||
|
|
|
|||
2
src/cmd/go/testdata/script/cache_vet.txt
vendored
2
src/cmd/go/testdata/script/cache_vet.txt
vendored
|
|
@ -1,7 +1,7 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
[short] skip
|
||||
[GODEBUG:gocacheverify] skip
|
||||
[GODEBUG:gocacheverify=1] skip
|
||||
[gccgo] skip # gccgo has no standard packages
|
||||
|
||||
# Start with a clean build cache:
|
||||
|
|
|
|||
25
src/cmd/go/testdata/script/cover_modes.txt
vendored
Normal file
25
src/cmd/go/testdata/script/cover_modes.txt
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Coverage analysis should use 'set' mode by default,
|
||||
# and should merge coverage profiles correctly.
|
||||
|
||||
[short] skip
|
||||
[gccgo] skip # gccgo has no cover tool
|
||||
|
||||
go test -short -cover encoding/binary errors -coverprofile=$WORK/cover.out
|
||||
! stderr '[^0-9]0\.0%'
|
||||
! stdout '[^0-9]0\.0%'
|
||||
|
||||
grep -count=1 '^mode: set$' $WORK/cover.out
|
||||
grep 'errors\.go' $WORK/cover.out
|
||||
grep 'binary\.go' $WORK/cover.out
|
||||
|
||||
[!race] stop
|
||||
|
||||
go test -short -race -cover encoding/binary errors -coverprofile=$WORK/cover.out
|
||||
! stderr '[^0-9]0\.0%'
|
||||
! stdout '[^0-9]0\.0%'
|
||||
|
||||
grep -count=1 '^mode: atomic$' $WORK/cover.out
|
||||
grep 'errors\.go' $WORK/cover.out
|
||||
grep 'binary\.go' $WORK/cover.out
|
||||
26
src/cmd/go/testdata/script/devnull.txt
vendored
Normal file
26
src/cmd/go/testdata/script/devnull.txt
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Issue 28035: go test -c -o NUL should work.
|
||||
# Issue 28549: go test -c -o /dev/null should not overwrite /dev/null when run as root.
|
||||
cd x
|
||||
cmp $devnull $WORK/empty.txt
|
||||
go test -o=$devnull -c
|
||||
! exists x.test$GOEXE
|
||||
cmp $devnull $WORK/empty.txt
|
||||
|
||||
# Issue 12407: go build -o /dev/null should succeed.
|
||||
cd ..
|
||||
go build -o $devnull y
|
||||
cmp $devnull $WORK/empty.txt
|
||||
|
||||
-- x/x_test.go --
|
||||
package x_test
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
func TestNUL(t *testing.T) {
|
||||
}
|
||||
-- y/y.go --
|
||||
package y
|
||||
func main() {}
|
||||
-- $WORK/empty.txt --
|
||||
53
src/cmd/go/testdata/script/gopath_install.txt
vendored
Normal file
53
src/cmd/go/testdata/script/gopath_install.txt
vendored
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Regression test for 'go install' locations in GOPATH mode.
|
||||
env GO111MODULE=off
|
||||
[short] skip
|
||||
|
||||
# Without $GOBIN set, binaries should be installed into the GOPATH bin directory.
|
||||
env GOBIN=
|
||||
rm $GOPATH/bin/go-cmd-test$GOEXE
|
||||
go install go-cmd-test
|
||||
exists $GOPATH/bin/go-cmd-test$GOEXE
|
||||
|
||||
# With $GOBIN set, binaries should be installed to $GOBIN.
|
||||
env GOBIN=$WORK/bin1
|
||||
mkdir -p $GOBIN
|
||||
go install go-cmd-test
|
||||
exists $GOBIN/go-cmd-test$GOEXE
|
||||
|
||||
# Issue 11065: installing to the current directory should create an executable.
|
||||
cd go-cmd-test
|
||||
env GOBIN=$PWD
|
||||
go install
|
||||
exists ./go-cmd-test$GOEXE
|
||||
cd ..
|
||||
|
||||
# Without $GOBIN set, installing a program outside $GOPATH should fail
|
||||
# (there is nowhere to install it).
|
||||
env GOPATH= # reset to default ($HOME/go, which does not exist)
|
||||
env GOBIN=
|
||||
! go install go-cmd-test/helloworld.go
|
||||
stderr '^go install: no install location for \.go files listed on command line \(GOBIN not set\)$'
|
||||
|
||||
# With $GOBIN set, should install there.
|
||||
env GOBIN=$WORK/bin1
|
||||
go install go-cmd-test/helloworld.go
|
||||
exists $GOBIN/helloworld$GOEXE
|
||||
|
||||
# We can't assume that we can write to GOROOT, because it may not be writable.
|
||||
# However, we can check its install location using 'go list'.
|
||||
# cmd/fix should be installed to GOROOT/pkg, not GOPATH/bin.
|
||||
env GOPATH=$PWD
|
||||
go list -f '{{.Target}}' cmd/fix
|
||||
stdout $GOROOT'[/\\]pkg[/\\]tool[/\\]'$GOOS'_'$GOARCH'[/\\]fix'$GOEXE'$'
|
||||
|
||||
# GOBIN should not affect toolchain install locations.
|
||||
env GOBIN=$WORK/bin1
|
||||
go list -f '{{.Target}}' cmd/fix
|
||||
stdout $GOROOT'[/\\]pkg[/\\]tool[/\\]'$GOOS'_'$GOARCH'[/\\]fix'$GOEXE'$'
|
||||
|
||||
-- go-cmd-test/helloworld.go --
|
||||
package main
|
||||
|
||||
func main() {
|
||||
println("hello world")
|
||||
}
|
||||
117
src/cmd/go/testdata/script/gopath_local.txt
vendored
Normal file
117
src/cmd/go/testdata/script/gopath_local.txt
vendored
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
env GO111MODULE=off # Relative imports only work in GOPATH mode.
|
||||
|
||||
[short] skip
|
||||
|
||||
# Imports should be resolved relative to the source file.
|
||||
go build testdata/local/easy.go
|
||||
exec ./easy$GOEXE
|
||||
stdout '^easysub\.Hello'
|
||||
|
||||
# Ignored files should be able to import the package built from
|
||||
# non-ignored files in the same directory.
|
||||
go build -o easysub$GOEXE testdata/local/easysub/main.go
|
||||
exec ./easysub$GOEXE
|
||||
stdout '^easysub\.Hello'
|
||||
|
||||
# Files in relative-imported packages should be able to
|
||||
# use relative imports themselves.
|
||||
go build testdata/local/hard.go
|
||||
exec ./hard$GOEXE
|
||||
stdout '^sub\.Hello'
|
||||
|
||||
# Explicit source files listed on the command line should not install without
|
||||
# GOBIN set, since individual source files aren't part of the containing GOPATH.
|
||||
! go install testdata/local/easy.go
|
||||
stderr '^go install: no install location for \.go files listed on command line \(GOBIN not set\)$'
|
||||
|
||||
[windows] stop # Windows does not allow the ridiculous directory name we're about to use.
|
||||
|
||||
env BAD_DIR_NAME='#$%:, &()*;<=>?\^{}'
|
||||
|
||||
mkdir -p testdata/$BAD_DIR_NAME/easysub
|
||||
mkdir -p testdata/$BAD_DIR_NAME/sub/sub
|
||||
|
||||
cp testdata/local/easy.go testdata/$BAD_DIR_NAME/easy.go
|
||||
cp testdata/local/easysub/easysub.go testdata/$BAD_DIR_NAME/easysub/easysub.go
|
||||
cp testdata/local/easysub/main.go testdata/$BAD_DIR_NAME/easysub/main.go
|
||||
cp testdata/local/hard.go testdata/$BAD_DIR_NAME/hard.go
|
||||
cp testdata/local/sub/sub.go testdata/$BAD_DIR_NAME/sub/sub.go
|
||||
cp testdata/local/sub/sub/subsub.go testdata/$BAD_DIR_NAME/sub/sub/subsub.go
|
||||
|
||||
# Imports should be resolved relative to the source file.
|
||||
go build testdata/$BAD_DIR_NAME/easy.go
|
||||
exec ./easy$GOEXE
|
||||
stdout '^easysub\.Hello'
|
||||
|
||||
# Ignored files should be able to import the package built from
|
||||
# non-ignored files in the same directory.
|
||||
go build -o easysub$GOEXE testdata/$BAD_DIR_NAME/easysub/main.go
|
||||
exec ./easysub$GOEXE
|
||||
stdout '^easysub\.Hello'
|
||||
|
||||
# Files in relative-imported packages should be able to
|
||||
# use relative imports themselves.
|
||||
go build testdata/$BAD_DIR_NAME/hard.go
|
||||
exec ./hard$GOEXE
|
||||
stdout '^sub\.Hello'
|
||||
|
||||
# Explicit source files listed on the command line should not install without
|
||||
# GOBIN set, since individual source files aren't part of the containing GOPATH.
|
||||
! go install testdata/$BAD_DIR_NAME/easy.go
|
||||
stderr '^go install: no install location for \.go files listed on command line \(GOBIN not set\)$'
|
||||
|
||||
-- testdata/local/easy.go --
|
||||
package main
|
||||
|
||||
import "./easysub"
|
||||
|
||||
func main() {
|
||||
easysub.Hello()
|
||||
}
|
||||
-- testdata/local/easysub/easysub.go --
|
||||
package easysub
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Hello() {
|
||||
fmt.Println("easysub.Hello")
|
||||
}
|
||||
-- testdata/local/easysub/main.go --
|
||||
// +build ignore
|
||||
|
||||
package main
|
||||
|
||||
import "."
|
||||
|
||||
func main() {
|
||||
easysub.Hello()
|
||||
}
|
||||
-- testdata/local/hard.go --
|
||||
package main
|
||||
|
||||
import "./sub"
|
||||
|
||||
func main() {
|
||||
sub.Hello()
|
||||
}
|
||||
-- testdata/local/sub/sub.go --
|
||||
package sub
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
subsub "./sub"
|
||||
)
|
||||
|
||||
func Hello() {
|
||||
fmt.Println("sub.Hello")
|
||||
subsub.Hello()
|
||||
}
|
||||
-- testdata/local/sub/sub/subsub.go --
|
||||
package subsub
|
||||
|
||||
import "fmt"
|
||||
|
||||
func Hello() {
|
||||
fmt.Println("subsub.Hello")
|
||||
}
|
||||
68
src/cmd/go/testdata/script/gopath_moved_repo.txt
vendored
Normal file
68
src/cmd/go/testdata/script/gopath_moved_repo.txt
vendored
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Test that 'go get -u' reports packages whose VCS configurations do not
|
||||
# match their import paths.
|
||||
|
||||
[!net] skip
|
||||
[short] skip
|
||||
|
||||
# We need to execute a custom Go program to break the config files.
|
||||
#
|
||||
# git will ask for a username and password when we run 'go get -d -f -u',
|
||||
# so we also need to set GIT_ASKPASS. Conveniently, a single binary can
|
||||
# perform both tasks!
|
||||
|
||||
go build -o replace.exe replace
|
||||
env GIT_ASKPASS=$PWD/replace.exe
|
||||
|
||||
|
||||
# Test that 'go get -u' reports moved git packages.
|
||||
|
||||
[exec:git] go get -d rsc.io/pdf
|
||||
[exec:git] go get -d -u rsc.io/pdf
|
||||
[exec:git] exec ./replace.exe pdf rsc.io/pdf/.git/config
|
||||
|
||||
[exec:git] ! go get -d -u rsc.io/pdf
|
||||
[exec:git] stderr 'is a custom import path for'
|
||||
[exec:git] ! go get -d -f -u rsc.io/pdf
|
||||
[exec:git] stderr 'validating server certificate|[nN]ot [fF]ound'
|
||||
|
||||
|
||||
# Test that 'go get -u' reports moved Mercurial packages.
|
||||
|
||||
[exec:hg] go get -d vcs-test.golang.org/go/custom-hg-hello
|
||||
[exec:hg] go get -d -u vcs-test.golang.org/go/custom-hg-hello
|
||||
[exec:hg] exec ./replace.exe custom-hg-hello vcs-test.golang.org/go/custom-hg-hello/.hg/hgrc
|
||||
|
||||
[exec:hg] ! go get -d -u vcs-test.golang.org/go/custom-hg-hello
|
||||
[exec:hg] stderr 'is a custom import path for'
|
||||
[exec:hg] ! go get -d -f -u vcs-test.golang.org/go/custom-hg-hello
|
||||
[exec:hg] stderr 'validating server certificate|[nN]ot [fF]ound'
|
||||
|
||||
|
||||
-- replace/replace.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 3 {
|
||||
return
|
||||
}
|
||||
|
||||
base := []byte(os.Args[1])
|
||||
path := os.Args[2]
|
||||
data, err := ioutil.ReadFile(path)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile(path, bytes.ReplaceAll(data, base, append(base, "XXX"...)), 0644)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
43
src/cmd/go/testdata/script/gopath_paths.txt
vendored
Normal file
43
src/cmd/go/testdata/script/gopath_paths.txt
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Regression test for GOPATH validation in GOPATH mode.
|
||||
env GO111MODULE=off
|
||||
|
||||
env ORIG_GOPATH=$GOPATH
|
||||
|
||||
# The literal path '.' in GOPATH should be rejected.
|
||||
env GOPATH=.
|
||||
! go build go-cmd-test/helloworld.go
|
||||
stderr 'GOPATH entry is relative'
|
||||
|
||||
# It should still be rejected if the requested package can be
|
||||
# found using another entry.
|
||||
env GOPATH=${:}$ORIG_GOPATH${:}.
|
||||
! go build go-cmd-test
|
||||
stderr 'GOPATH entry is relative'
|
||||
|
||||
# GOPATH cannot be a relative subdirectory of the working directory.
|
||||
env ORIG_GOPATH
|
||||
stdout 'ORIG_GOPATH='$WORK[/\\]gopath
|
||||
cd $WORK
|
||||
env GOPATH=gopath
|
||||
! go build gopath/src/go-cmd-test/helloworld.go
|
||||
stderr 'GOPATH entry is relative'
|
||||
|
||||
# Blank paths in GOPATH should be rejected as relative (issue 21928).
|
||||
env GOPATH=' '${:}$ORIG_GOPATH
|
||||
! go build go-cmd-test
|
||||
stderr 'GOPATH entry is relative'
|
||||
|
||||
[short] stop
|
||||
|
||||
# Empty paths in GOPATH should be ignored (issue 21928).
|
||||
env GOPATH=${:}$ORIG_GOPATH
|
||||
env GOPATH
|
||||
go install go-cmd-test
|
||||
exists $ORIG_GOPATH/bin/go-cmd-test$GOEXE
|
||||
|
||||
-- go-cmd-test/helloworld.go --
|
||||
package main
|
||||
|
||||
func main() {
|
||||
println("hello world")
|
||||
}
|
||||
114
src/cmd/go/testdata/script/import_main.txt
vendored
Normal file
114
src/cmd/go/testdata/script/import_main.txt
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Test that you cannot import a main package.
|
||||
# See golang.org/issue/4210 and golang.org/issue/17475.
|
||||
|
||||
[short] skip
|
||||
cd $WORK
|
||||
|
||||
# Importing package main from that package main's test should work.
|
||||
go build x
|
||||
go test -c x
|
||||
|
||||
# Importing package main from another package should fail.
|
||||
! go build p1
|
||||
stderr 'import "x" is a program, not an importable package'
|
||||
|
||||
# ... even in that package's test.
|
||||
go build p2
|
||||
! go test -c p2
|
||||
stderr 'import "x" is a program, not an importable package'
|
||||
|
||||
# ... even if that package's test is an xtest.
|
||||
go build p3
|
||||
! go test p3
|
||||
stderr 'import "x" is a program, not an importable package'
|
||||
|
||||
# ... even if that package is a package main
|
||||
go build p4
|
||||
! go test -c p4
|
||||
stderr 'import "x" is a program, not an importable package'
|
||||
|
||||
# ... even if that package is a package main using an xtest.
|
||||
go build p5
|
||||
! go test -c p5
|
||||
stderr 'import "x" is a program, not an importable package'
|
||||
|
||||
-- x/main.go --
|
||||
package main
|
||||
|
||||
var X int
|
||||
|
||||
func main() {}
|
||||
-- x/main_test.go --
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
xmain "x"
|
||||
)
|
||||
|
||||
var _ = xmain.X
|
||||
|
||||
func TestFoo(t *testing.T) {}
|
||||
-- p1/p.go --
|
||||
package p1
|
||||
|
||||
import xmain "x"
|
||||
|
||||
var _ = xmain.X
|
||||
-- p2/p.go --
|
||||
package p2
|
||||
-- p2/p_test.go --
|
||||
package p2
|
||||
|
||||
import (
|
||||
"testing"
|
||||
xmain "x"
|
||||
)
|
||||
|
||||
var _ = xmain.X
|
||||
|
||||
func TestFoo(t *testing.T) {}
|
||||
-- p3/p.go --
|
||||
package p
|
||||
-- p3/p_test.go --
|
||||
package p_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
xmain "x"
|
||||
)
|
||||
|
||||
var _ = xmain.X
|
||||
|
||||
func TestFoo(t *testing.T) {}
|
||||
-- p4/p.go --
|
||||
package main
|
||||
|
||||
func main() {}
|
||||
-- p4/p_test.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
xmain "x"
|
||||
)
|
||||
|
||||
var _ = xmain.X
|
||||
|
||||
func TestFoo(t *testing.T) {}
|
||||
-- p5/p.go --
|
||||
package main
|
||||
func main() {}
|
||||
-- p5/p_test.go --
|
||||
package main_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
xmain "x"
|
||||
)
|
||||
|
||||
var _ = xmain.X
|
||||
|
||||
func TestFoo(t *testing.T) {}
|
||||
16
src/cmd/go/testdata/script/list_linkshared.txt
vendored
Normal file
16
src/cmd/go/testdata/script/list_linkshared.txt
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
# golang.org/issue/35759: 'go list -linkshared'
|
||||
# panicked if invoked on a test-only package.
|
||||
|
||||
[!buildmode:shared] skip
|
||||
|
||||
go list -f '{{.ImportPath}}: {{.Target}} {{.Shlib}}' -linkshared .
|
||||
stdout '^example.com: $'
|
||||
|
||||
-- go.mod --
|
||||
module example.com
|
||||
|
||||
go 1.14
|
||||
-- x.go --
|
||||
package x
|
||||
4
src/cmd/go/testdata/script/mod_cache_rw.txt
vendored
4
src/cmd/go/testdata/script/mod_cache_rw.txt
vendored
|
|
@ -19,8 +19,8 @@ cp $WORK/extraneous.txt $GOPATH/pkg/mod/rsc.io/quote@v1.5.2/extraneous_file.go
|
|||
# should be able to remove the module cache if the '-rf' flags are set.
|
||||
[!windows] [exec:rm] exec rm -rf $GOPATH/pkg/mod
|
||||
[!windows] [!exec:rm] go clean -modcache
|
||||
[windows] [exec:rmdir] exec rmdir /s /q $GOPATH\pkg\mod
|
||||
[windows] [!exec:rmdir] go clean -modcache
|
||||
[windows] [exec:cmd.exe] exec cmd.exe /c rmdir /s /q $GOPATH\pkg\mod
|
||||
[windows] [!exec:cmd.exe] go clean -modcache
|
||||
! exists $GOPATH/pkg/mod
|
||||
|
||||
# The directories in the module cache should by default be unwritable,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
env GO111MODULE=on
|
||||
|
||||
[!net] skip
|
||||
[!exec:git] skip
|
||||
|
||||
# secure fetch should report insecure warning
|
||||
cd $WORK/test
|
||||
go mod init
|
||||
|
|
|
|||
7
src/cmd/go/testdata/script/mod_download.txt
vendored
7
src/cmd/go/testdata/script/mod_download.txt
vendored
|
|
@ -4,6 +4,7 @@ env GOPROXY=$GOPROXY/quiet
|
|||
# download with version should print nothing
|
||||
go mod download rsc.io/quote@v1.5.0
|
||||
! stdout .
|
||||
! stderr .
|
||||
|
||||
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.info
|
||||
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.5.0.mod
|
||||
|
|
@ -106,5 +107,11 @@ rm $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.2.1.zip
|
|||
go mod download rsc.io/quote@v1.2.1
|
||||
exists $GOPATH/pkg/mod/cache/download/rsc.io/quote/@v/v1.2.1.zip
|
||||
|
||||
# download -x with version should print
|
||||
# the underlying commands such as contacting GOPROXY.
|
||||
go mod download -x rsc.io/quote@v1.0.0
|
||||
! stdout .
|
||||
stderr 'get '$GOPROXY
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ env GO111MODULE=on
|
|||
[short] skip
|
||||
|
||||
go mod init example.com
|
||||
go get golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0
|
||||
go get golang.org/x/text@v0.3.0 golang.org/x/internal@v0.1.0 golang.org/x/exp@none
|
||||
|
|
|
|||
7
src/cmd/go/testdata/script/mod_outside.txt
vendored
7
src/cmd/go/testdata/script/mod_outside.txt
vendored
|
|
@ -56,6 +56,13 @@ stderr 'go: cannot match "all": working directory is not part of a module'
|
|||
stderr 'go: cannot match "all": working directory is not part of a module'
|
||||
! stdout 'example.com/version'
|
||||
|
||||
# 'go list -m' with wildcards should fail. Wildcards match modules in the
|
||||
# build list, so they aren't meaningful outside a module.
|
||||
! go list -m ...
|
||||
stderr 'go: cannot match "...": working directory is not part of a module'
|
||||
! go list -m rsc.io/quote/...
|
||||
stderr 'go: cannot match "rsc.io/quote/...": working directory is not part of a module'
|
||||
|
||||
|
||||
# 'go clean' should skip the current directory if it isn't in a module.
|
||||
go clean -n
|
||||
|
|
|
|||
19
src/cmd/go/testdata/script/modfile_flag.txt
vendored
19
src/cmd/go/testdata/script/modfile_flag.txt
vendored
|
|
@ -44,6 +44,19 @@ exists vendor
|
|||
go mod edit -require rsc.io/quote@v1.5.1
|
||||
! go list .
|
||||
go list -mod=mod
|
||||
rm vendor
|
||||
|
||||
|
||||
# 'go generate' should use the alternate file when resolving packages.
|
||||
# Recursive go commands started with 'go generate' should not get an explicitly
|
||||
# passed -modfile, but they should see arguments from GOFLAGS.
|
||||
cp go.alt.mod go.gen.mod
|
||||
env OLD_GOFLAGS=$GOFLAGS
|
||||
env GOFLAGS=-modfile=go.gen.mod
|
||||
go generate -modfile=go.alt.mod .
|
||||
env GOFLAGS=$OLD_GOFLAGS
|
||||
grep example.com/exclude go.gen.mod
|
||||
! grep example.com/exclude go.alt.mod
|
||||
|
||||
|
||||
# The original files should not have been modified.
|
||||
|
|
@ -62,6 +75,10 @@ stderr '-modfile=goaltmod: file does not have .mod extension'
|
|||
-- go.sum --
|
||||
ʕ◔ϖ◔ʔ
|
||||
-- use.go --
|
||||
package use
|
||||
package main
|
||||
|
||||
import _ "rsc.io/quote"
|
||||
-- gen.go --
|
||||
//go:generate go mod edit -exclude example.com/exclude@v1.0.0
|
||||
|
||||
package main
|
||||
|
|
|
|||
230
src/cmd/go/testdata/script/test_cache_inputs.txt
vendored
Normal file
230
src/cmd/go/testdata/script/test_cache_inputs.txt
vendored
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Test that cached test results are invalidated in response to
|
||||
# changes to the external inputs to the test.
|
||||
|
||||
[short] skip
|
||||
[GODEBUG:gocacheverify=1] skip
|
||||
|
||||
# We're testing cache behavior, so start with a clean GOCACHE.
|
||||
env GOCACHE=$WORK/cache
|
||||
|
||||
# Build a helper binary to invoke os.Chtimes.
|
||||
go build -o mkold$GOEXE mkold.go
|
||||
|
||||
# Make test input files appear to be a minute old.
|
||||
exec ./mkold$GOEXE 1m testcache/file.txt
|
||||
exec ./mkold$GOEXE 1m testcache/script.sh
|
||||
|
||||
# If the test reads an environment variable, changes to that variable
|
||||
# should invalidate cached test results.
|
||||
env TESTKEY=x
|
||||
go test testcache -run=TestLookupEnv
|
||||
go test testcache -run=TestLookupEnv
|
||||
stdout '\(cached\)'
|
||||
|
||||
env TESTKEY=y
|
||||
go test testcache -run=TestLookupEnv
|
||||
! stdout '\(cached\)'
|
||||
go test testcache -run=TestLookupEnv
|
||||
stdout '\(cached\)'
|
||||
|
||||
# If the test stats a file, changes to the file should invalidate the cache.
|
||||
go test testcache -run=FileSize
|
||||
go test testcache -run=FileSize
|
||||
stdout '\(cached\)'
|
||||
|
||||
cp 4x.txt testcache/file.txt
|
||||
go test testcache -run=FileSize
|
||||
! stdout '\(cached\)'
|
||||
go test testcache -run=FileSize
|
||||
stdout '\(cached\)'
|
||||
|
||||
# Files should be tracked even if the test changes its working directory.
|
||||
go test testcache -run=Chdir
|
||||
go test testcache -run=Chdir
|
||||
stdout '\(cached\)'
|
||||
cp 6x.txt testcache/file.txt
|
||||
go test testcache -run=Chdir
|
||||
! stdout '\(cached\)'
|
||||
go test testcache -run=Chdir
|
||||
stdout '\(cached\)'
|
||||
|
||||
# The content of files should affect caching, provided that the mtime also changes.
|
||||
exec ./mkold$GOEXE 1m testcache/file.txt
|
||||
go test testcache -run=FileContent
|
||||
go test testcache -run=FileContent
|
||||
stdout '\(cached\)'
|
||||
cp 2y.txt testcache/file.txt
|
||||
exec ./mkold$GOEXE 50s testcache/file.txt
|
||||
go test testcache -run=FileContent
|
||||
! stdout '\(cached\)'
|
||||
go test testcache -run=FileContent
|
||||
stdout '\(cached\)'
|
||||
|
||||
# Directory contents read via os.ReadDirNames should affect caching.
|
||||
go test testcache -run=DirList
|
||||
go test testcache -run=DirList
|
||||
stdout '\(cached\)'
|
||||
rm testcache/file.txt
|
||||
go test testcache -run=DirList
|
||||
! stdout '\(cached\)'
|
||||
go test testcache -run=DirList
|
||||
stdout '\(cached\)'
|
||||
|
||||
# Files outside GOROOT and GOPATH should not affect caching.
|
||||
env TEST_EXTERNAL_FILE=$WORK/external.txt
|
||||
go test testcache -run=ExternalFile
|
||||
go test testcache -run=ExternalFile
|
||||
stdout '\(cached\)'
|
||||
|
||||
rm $WORK/external.txt
|
||||
go test testcache -run=ExternalFile
|
||||
stdout '\(cached\)'
|
||||
|
||||
# Executables within GOROOT and GOPATH should affect caching,
|
||||
# even if the test does not stat them explicitly.
|
||||
|
||||
[!exec:/bin/sh] skip
|
||||
chmod 0755 ./testcache/script.sh
|
||||
|
||||
exec ./mkold$GOEXEC 1m testcache/script.sh
|
||||
go test testcache -run=Exec
|
||||
go test testcache -run=Exec
|
||||
stdout '\(cached\)'
|
||||
|
||||
exec ./mkold$GOEXE 50s testcache/script.sh
|
||||
go test testcache -run=Exec
|
||||
! stdout '\(cached\)'
|
||||
go test testcache -run=Exec
|
||||
stdout '\(cached\)'
|
||||
|
||||
-- testcache/file.txt --
|
||||
xx
|
||||
-- 4x.txt --
|
||||
xxxx
|
||||
-- 6x.txt --
|
||||
xxxxxx
|
||||
-- 2y.txt --
|
||||
yy
|
||||
-- $WORK/external.txt --
|
||||
This file is outside of GOPATH.
|
||||
-- testcache/script.sh --
|
||||
#!/bin/sh
|
||||
exit 0
|
||||
-- testcache/testcache_test.go --
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package testcache
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChdir(t *testing.T) {
|
||||
os.Chdir("..")
|
||||
defer os.Chdir("testcache")
|
||||
info, err := os.Stat("testcache/file.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if info.Size()%2 != 1 {
|
||||
t.Fatal("even file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOddFileContent(t *testing.T) {
|
||||
f, err := os.Open("file.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := ioutil.ReadAll(f)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(data)%2 != 1 {
|
||||
t.Fatal("even file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOddFileSize(t *testing.T) {
|
||||
info, err := os.Stat("file.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if info.Size()%2 != 1 {
|
||||
t.Fatal("even file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOddGetenv(t *testing.T) {
|
||||
val := os.Getenv("TESTKEY")
|
||||
if len(val)%2 != 1 {
|
||||
t.Fatal("even env value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLookupEnv(t *testing.T) {
|
||||
_, ok := os.LookupEnv("TESTKEY")
|
||||
if !ok {
|
||||
t.Fatal("env missing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirList(t *testing.T) {
|
||||
f, err := os.Open(".")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Readdirnames(-1)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
// Note: not using os/exec to make sure there is no unexpected stat.
|
||||
p, err := os.StartProcess("./script.sh", []string{"script"}, new(os.ProcAttr))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ps, err := p.Wait()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ps.Success() {
|
||||
t.Fatalf("script failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExternalFile(t *testing.T) {
|
||||
os.Open(os.Getenv("TEST_EXTERNAL_FILE"))
|
||||
_, err := os.Stat(os.Getenv("TEST_EXTERNAL_FILE"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
-- mkold.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
d, err := time.ParseDuration(os.Args[1])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
path := os.Args[2]
|
||||
old := time.Now().Add(-d)
|
||||
err = os.Chtimes(path, old, old)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
15
src/cmd/go/testdata/script/test_devnull.txt
vendored
15
src/cmd/go/testdata/script/test_devnull.txt
vendored
|
|
@ -1,15 +0,0 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# go test -c -o NUL
|
||||
# should work (see golang.org/issue/28035).
|
||||
cd x
|
||||
go test -o=$devnull -c
|
||||
! exists x.test$GOEXE
|
||||
|
||||
-- x/x_test.go --
|
||||
package x_test
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
func TestNUL(t *testing.T) {
|
||||
}
|
||||
32
src/cmd/go/testdata/script/test_main_archive.txt
vendored
Normal file
32
src/cmd/go/testdata/script/test_main_archive.txt
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Test that a main_test of 'package main' imports the package,
|
||||
# not the installed binary.
|
||||
|
||||
[short] skip
|
||||
|
||||
env GOBIN=$WORK/bin
|
||||
go test main_test
|
||||
go install main_test
|
||||
|
||||
go list -f '{{.Stale}}' main_test
|
||||
stdout false
|
||||
|
||||
go test main_test
|
||||
|
||||
-- main_test/m.go --
|
||||
package main
|
||||
|
||||
func F() {}
|
||||
func main() {}
|
||||
-- main_test/m_test.go --
|
||||
package main_test
|
||||
|
||||
import (
|
||||
. "main_test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
F()
|
||||
}
|
||||
14
src/cmd/go/testdata/script/test_rebuildall.txt
vendored
Normal file
14
src/cmd/go/testdata/script/test_rebuildall.txt
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Regression test for golang.org/issue/6844:
|
||||
# 'go test -a' should force dependencies in the standard library to be rebuilt.
|
||||
|
||||
[short] skip
|
||||
|
||||
go test -x -a -c testdata/dep_test.go
|
||||
stderr '^.*[/\\]compile'$GOEXE'["]? (.* )?regexp .*[/\\]regexp\.go'
|
||||
|
||||
-- testdata/dep_test.go --
|
||||
package deps
|
||||
|
||||
import _ "testing"
|
||||
8
src/cmd/go/testdata/script/vet_flags.txt
vendored
Normal file
8
src/cmd/go/testdata/script/vet_flags.txt
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
env GO111MODULE=off
|
||||
|
||||
# Issue 35837. Verify that "go vet -<analyzer> <std package>" works if 'pwd' is not $GOROOT/src
|
||||
# we utilize the package runtime/testdata/testprog as the issue is specific to vetting standard package
|
||||
|
||||
go vet -n -unreachable=false runtime/testdata/testprog
|
||||
stderr '-unreachable=false'
|
||||
stderr '-unsafeptr=false'
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
package main
|
||||
|
||||
func main() {
|
||||
println("hello world")
|
||||
}
|
||||
4
src/cmd/go/testdata/src/main_test/m.go
vendored
4
src/cmd/go/testdata/src/main_test/m.go
vendored
|
|
@ -1,4 +0,0 @@
|
|||
package main
|
||||
|
||||
func F() {}
|
||||
func main() {}
|
||||
10
src/cmd/go/testdata/src/main_test/m_test.go
vendored
10
src/cmd/go/testdata/src/main_test/m_test.go
vendored
|
|
@ -1,10 +0,0 @@
|
|||
package main_test
|
||||
|
||||
import (
|
||||
. "main_test"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test1(t *testing.T) {
|
||||
F()
|
||||
}
|
||||
|
|
@ -1,91 +0,0 @@
|
|||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package testcache
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestChdir(t *testing.T) {
|
||||
os.Chdir("..")
|
||||
defer os.Chdir("testcache")
|
||||
info, err := os.Stat("testcache/file.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if info.Size()%2 != 1 {
|
||||
t.Fatal("even file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOddFileContent(t *testing.T) {
|
||||
f, err := os.Open("file.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
data, err := ioutil.ReadAll(f)
|
||||
f.Close()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(data)%2 != 1 {
|
||||
t.Fatal("even file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOddFileSize(t *testing.T) {
|
||||
info, err := os.Stat("file.txt")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if info.Size()%2 != 1 {
|
||||
t.Fatal("even file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOddGetenv(t *testing.T) {
|
||||
val := os.Getenv("TESTKEY")
|
||||
if len(val)%2 != 1 {
|
||||
t.Fatal("even env value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestLookupEnv(t *testing.T) {
|
||||
_, ok := os.LookupEnv("TESTKEY")
|
||||
if !ok {
|
||||
t.Fatal("env missing")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirList(t *testing.T) {
|
||||
f, err := os.Open(".")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
f.Readdirnames(-1)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
func TestExec(t *testing.T) {
|
||||
if runtime.GOOS == "plan9" || runtime.GOOS == "windows" {
|
||||
t.Skip("non-unix")
|
||||
}
|
||||
|
||||
// Note: not using os/exec to make sure there is no unexpected stat.
|
||||
p, err := os.StartProcess("./script.sh", []string{"script"}, new(os.ProcAttr))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ps, err := p.Wait()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !ps.Success() {
|
||||
t.Fatalf("script failed: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ package buildid
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"internal/obscuretestdata"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
|
|
@ -19,13 +20,6 @@ const (
|
|||
)
|
||||
|
||||
func TestReadFile(t *testing.T) {
|
||||
var files = []string{
|
||||
"p.a",
|
||||
"a.elf",
|
||||
"a.macho",
|
||||
"a.pe",
|
||||
}
|
||||
|
||||
f, err := ioutil.TempFile("", "buildid-test-")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
@ -34,26 +28,43 @@ func TestReadFile(t *testing.T) {
|
|||
defer os.Remove(tmp)
|
||||
f.Close()
|
||||
|
||||
for _, f := range files {
|
||||
id, err := ReadFile("testdata/" + f)
|
||||
// Use obscured files to prevent Apple’s notarization service from
|
||||
// mistaking them as candidates for notarization and rejecting the entire
|
||||
// toolchain.
|
||||
// See golang.org/issue/34986
|
||||
var files = []string{
|
||||
"p.a.base64",
|
||||
"a.elf.base64",
|
||||
"a.macho.base64",
|
||||
"a.pe.base64",
|
||||
}
|
||||
|
||||
for _, name := range files {
|
||||
f, err := obscuretestdata.DecodeToTempFile("testdata/" + name)
|
||||
if err != nil {
|
||||
t.Errorf("obscuretestdata.DecodeToTempFile(testdata/%s): %v", name, err)
|
||||
continue
|
||||
}
|
||||
defer os.Remove(f)
|
||||
id, err := ReadFile(f)
|
||||
if id != expectedID || err != nil {
|
||||
t.Errorf("ReadFile(testdata/%s) = %q, %v, want %q, nil", f, id, err, expectedID)
|
||||
}
|
||||
old := readSize
|
||||
readSize = 2048
|
||||
id, err = ReadFile("testdata/" + f)
|
||||
id, err = ReadFile(f)
|
||||
readSize = old
|
||||
if id != expectedID || err != nil {
|
||||
t.Errorf("ReadFile(testdata/%s) [readSize=2k] = %q, %v, want %q, nil", f, id, err, expectedID)
|
||||
t.Errorf("ReadFile(%s) [readSize=2k] = %q, %v, want %q, nil", f, id, err, expectedID)
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadFile("testdata/" + f)
|
||||
data, err := ioutil.ReadFile(f)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
m, _, err := FindAndHash(bytes.NewReader(data), expectedID, 1024)
|
||||
if err != nil {
|
||||
t.Errorf("FindAndHash(testdata/%s): %v", f, err)
|
||||
t.Errorf("FindAndHash(%s): %v", f, err)
|
||||
continue
|
||||
}
|
||||
if err := ioutil.WriteFile(tmp, data, 0666); err != nil {
|
||||
|
|
@ -68,7 +79,7 @@ func TestReadFile(t *testing.T) {
|
|||
err = Rewrite(tf, m, newID)
|
||||
err2 := tf.Close()
|
||||
if err != nil {
|
||||
t.Errorf("Rewrite(testdata/%s): %v", f, err)
|
||||
t.Errorf("Rewrite(%s): %v", f, err)
|
||||
continue
|
||||
}
|
||||
if err2 != nil {
|
||||
|
|
@ -77,7 +88,7 @@ func TestReadFile(t *testing.T) {
|
|||
|
||||
id, err = ReadFile(tmp)
|
||||
if id != newID || err != nil {
|
||||
t.Errorf("ReadFile(testdata/%s after Rewrite) = %q, %v, want %q, nil", f, id, err, newID)
|
||||
t.Errorf("ReadFile(%s after Rewrite) = %q, %v, want %q, nil", f, id, err, newID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
BIN
src/cmd/internal/buildid/testdata/a.elf
vendored
BIN
src/cmd/internal/buildid/testdata/a.elf
vendored
Binary file not shown.
1
src/cmd/internal/buildid/testdata/a.elf.base64
vendored
Normal file
1
src/cmd/internal/buildid/testdata/a.elf.base64
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/cmd/internal/buildid/testdata/a.macho
vendored
BIN
src/cmd/internal/buildid/testdata/a.macho
vendored
Binary file not shown.
1
src/cmd/internal/buildid/testdata/a.macho.base64
vendored
Normal file
1
src/cmd/internal/buildid/testdata/a.macho.base64
vendored
Normal file
File diff suppressed because one or more lines are too long
BIN
src/cmd/internal/buildid/testdata/a.pe
vendored
BIN
src/cmd/internal/buildid/testdata/a.pe
vendored
Binary file not shown.
1
src/cmd/internal/buildid/testdata/a.pe.base64
vendored
Normal file
1
src/cmd/internal/buildid/testdata/a.pe.base64
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
TVqQAAMABAAAAAAA//8AAIsAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAAZIYEAAAAAAAADAAAAAAAAPAAIwILAgMAAAIAAAACAAAAAAAAcBAAAAAQAAAAAEAAAAAAAAAQAAAAAgAABAAAAAEAAAAEAAAAAAAAAABQAAAABgAAAAAAAAMAAAAAACAAAAAAAADgHwAAAAAAAAAQAAAAAAAAEAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAMAAAFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAudGV4dAAAAMYBAAAAEAAAAAIAAAAGAAAAAAAAAAAAAAAAAABgAABgLmRhdGEAAADgAQAAACAAAAACAAAACAAAAAAAAAAAAAAAAAAAQAAAwC5pZGF0YQAAFAAAAAAwAAAAAgAAAAoAAAAAAAAAAAAAAAAAAEAAAMAuc3ltdGFiAAQAAAAAQAAAAAIAAAAMAAAAAAAAAAAAAAAAAAAAAABCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/yBHbyBidWlsZCBJRDogImFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6LjEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQiCiD/zMPMzMzMzMzMzMzMzMzMzMwBAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAEEAAAAAAAAAAAAAAAAAA+////wAAAQgCAAAAAAAAAAAQQAAAAAAAQAAAAAAAAABwEEAAAAAAAHgAAAAAAAAAcRBAAAAAAADIAAAAAAAAAAAQQAAAAAAAaAAAAAAAAABnRSMBAAAAAAAAAAAAAAAAAAAAAAAAAABnby5idWlsZGlkAAAAAAAAcBBAAAAAAACwAAAAAAAAAGdFIwG7AAAAvgAAAMEAAAAAAAAAAgAAAIAQQAAAAAAAgBBAAAAAAABtYWluLm1haW4AAAIBAAQBAAYBAAAAAAACAAAA0AAAAC9Vc2Vycy9yc2MvZ28vc3JjL2NtZC9pbnRlcm5hbC9idWlsZGlkL3Rlc3RkYXRhL3AuZ28AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgIEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAQQAAAAAAABgEAAAAAAAAGAQAAAAAAANAQQAAAAAAAAwAAAAAAAAADAAAAAAAAAIgRQAAAAAAAAgAAAAAAAAACAAAAAAAAAIwQQAAAAAAAABBAAAAAAABxEEAAAAAAAAAQQAAAAAAAgBBAAAAAAAAAIEAAAAAAAOAhQAAAAAAA4CFAAAAAAADgIUAAAAAAAOAhQAAAAAAA4CFAAAAAAADgIUAAAAAAAOAhQAAAAAAA4CFAAAAAAACJEEAAAAAAAIgQQAAAAAAAgBBAAAAAAAC4EEAAAAAAAKAQQAAAAAAAAQAAAAAAAAABAAAAAAAAALgQQAAAAAAAAAAAAAAAAAAAAAAAAAAAALgQQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
BIN
src/cmd/internal/buildid/testdata/p.a
vendored
BIN
src/cmd/internal/buildid/testdata/p.a
vendored
Binary file not shown.
1
src/cmd/internal/buildid/testdata/p.a.base64
vendored
Normal file
1
src/cmd/internal/buildid/testdata/p.a.base64
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
ITxhcmNoPgpfXy5QS0dERUYgICAgICAgMCAgICAgICAgICAgMCAgICAgMCAgICAgNjQ0ICAgICAzMzAgICAgICAgYApnbyBvYmplY3QgZGFyd2luIGFtZDY0IGRldmVsICszYjMzYWY1ZDY4IFRodSBPY3QgNSAxNjo1OTowMCAyMDE3IC0wNDAwIFg6ZnJhbWVwb2ludGVyCmJ1aWxkIGlkICJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei4xMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0IgotLS0tCgpidWlsZCBpZCAiYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXouMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNCIKCiQkQgp2ZXJzaW9uIDUKCgACAQFwAAsACwABAAokJApfZ29fLm8gICAgICAgICAgMCAgICAgICAgICAgMCAgICAgMCAgICAgNjQ0ICAgICAyMjMgICAgICAgYApnbyBvYmplY3QgZGFyd2luIGFtZDY0IGRldmVsICszYjMzYWY1ZDY4IFRodSBPY3QgNSAxNjo1OTowMCAyMDE3IC0wNDAwIFg6ZnJhbWVwb2ludGVyCmJ1aWxkIGlkICJhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ei4xMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0IgotLS0tCgoKIQoAAGdvMTlsZAEA/wAAAAAAAP//Z28xOWxkAA==
|
||||
|
|
@ -674,6 +674,12 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// CMP stackguard, SP
|
||||
|
|
@ -757,6 +763,8 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
bls.As = ABLS
|
||||
bls.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
|
||||
|
||||
var last *obj.Prog
|
||||
for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
|
@ -768,7 +776,8 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
|
||||
pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
|
||||
pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
|
||||
|
||||
// MOVW LR, R3
|
||||
movw := obj.Appendp(pcdata, c.newprog)
|
||||
|
|
@ -793,14 +802,16 @@ func (c *ctxt5) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
}
|
||||
call.To.Sym = c.ctxt.Lookup(morestack)
|
||||
|
||||
pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
|
||||
|
||||
// B start
|
||||
b := obj.Appendp(call, c.newprog)
|
||||
b := obj.Appendp(pcdata, c.newprog)
|
||||
b.As = obj.AJMP
|
||||
b.To.Type = obj.TYPE_BRANCH
|
||||
b.Pcond = c.cursym.Func.Text.Link
|
||||
b.Spadj = +framesize
|
||||
|
||||
return bls
|
||||
return end
|
||||
}
|
||||
|
||||
var unaryDst = map[obj.As]bool{
|
||||
|
|
|
|||
|
|
@ -53,12 +53,17 @@ Special Cases.
|
|||
|
||||
(3) No need to add "W" suffix: LDARB, LDARH, LDAXRB, LDAXRH, LDTRH, LDXRB, LDXRH.
|
||||
|
||||
(4) In Go assembly syntax, NOP is a zero-width pseudo-instruction serves generic purpose, nothing
|
||||
related to real ARM64 instruction. NOOP serves for the hardware nop instruction. NOOP is an alias of
|
||||
HINT $0.
|
||||
|
||||
Examples:
|
||||
VMOV V13.B[1], R20 <=> mov x20, v13.b[1]
|
||||
VMOV V13.H[1], R20 <=> mov w20, v13.h[1]
|
||||
JMP (R3) <=> br x3
|
||||
CALL (R17) <=> blr x17
|
||||
LDAXRB (R19), R16 <=> ldaxrb w16, [x19]
|
||||
NOOP <=> nop
|
||||
|
||||
|
||||
Register mapping rules
|
||||
|
|
|
|||
|
|
@ -62,6 +62,12 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
q := (*obj.Prog)(nil)
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
|
|
@ -156,6 +162,8 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
bls.As = ABLS
|
||||
bls.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
end := c.ctxt.EndUnsafePoint(bls, c.newprog, -1)
|
||||
|
||||
var last *obj.Prog
|
||||
for last = c.cursym.Func.Text; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
|
@ -167,7 +175,8 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
|
||||
pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
|
||||
pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
|
||||
|
||||
// MOV LR, R3
|
||||
movlr := obj.Appendp(pcdata, c.newprog)
|
||||
|
|
@ -204,18 +213,16 @@ func (c *ctxt7) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
}
|
||||
call.To.Sym = c.ctxt.Lookup(morestack)
|
||||
|
||||
pcdata = c.ctxt.EndUnsafePoint(call, c.newprog, -1)
|
||||
|
||||
// B start
|
||||
jmp := obj.Appendp(call, c.newprog)
|
||||
jmp := obj.Appendp(pcdata, c.newprog)
|
||||
jmp.As = AB
|
||||
jmp.To.Type = obj.TYPE_BRANCH
|
||||
jmp.Pcond = c.cursym.Func.Text.Link
|
||||
jmp.Spadj = +framesize
|
||||
|
||||
// placeholder for bls's jump target
|
||||
// p = obj.Appendp(ctxt, p)
|
||||
// p.As = obj.ANOP
|
||||
|
||||
return bls
|
||||
return end
|
||||
}
|
||||
|
||||
func progedit(ctxt *obj.Link, p *obj.Prog, newprog obj.ProgAlloc) {
|
||||
|
|
|
|||
|
|
@ -677,6 +677,12 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R1
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
var q *obj.Prog
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
|
|
@ -796,7 +802,7 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
p.Mark |= LABEL
|
||||
}
|
||||
|
||||
p = c.ctxt.EmitEntryLiveness(c.cursym, p, c.newprog)
|
||||
p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
|
||||
|
||||
// JAL runtime.morestack(SB)
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
|
@ -812,6 +818,8 @@ func (c *ctxt0) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
}
|
||||
p.Mark |= BRANCH
|
||||
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
|
||||
// JMP start
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
|
|
|
|||
|
|
@ -187,6 +187,13 @@ func (ctxt *Link) Globl(s *LSym, size int64, flag int) {
|
|||
// liveness map active at the entry of function s. It returns the last
|
||||
// Prog generated.
|
||||
func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := ctxt.EmitEntryStackMap(s, p, newprog)
|
||||
pcdata = ctxt.EmitEntryRegMap(s, pcdata, newprog)
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// Similar to EmitEntryLiveness, but just emit stack map.
|
||||
func (ctxt *Link) EmitEntryStackMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := Appendp(p, newprog)
|
||||
pcdata.Pos = s.Func.Text.Pos
|
||||
pcdata.As = APCDATA
|
||||
|
|
@ -195,8 +202,12 @@ func (ctxt *Link) EmitEntryLiveness(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
|||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = -1 // pcdata starts at -1 at function entry
|
||||
|
||||
// Same, with register map.
|
||||
pcdata = Appendp(pcdata, newprog)
|
||||
return pcdata
|
||||
}
|
||||
|
||||
// Similar to EmitEntryLiveness, but just emit register map.
|
||||
func (ctxt *Link) EmitEntryRegMap(s *LSym, p *Prog, newprog ProgAlloc) *Prog {
|
||||
pcdata := Appendp(p, newprog)
|
||||
pcdata.Pos = s.Func.Text.Pos
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
|
|
@ -215,12 +226,10 @@ func (ctxt *Link) StartUnsafePoint(p *Prog, newprog ProgAlloc) *Prog {
|
|||
pcdata := Appendp(p, newprog)
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
pcdata.From.Offset = objabi.PCDATA_StackMapIndex
|
||||
pcdata.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = -2 // pcdata -2 marks unsafe point
|
||||
|
||||
// TODO: register map?
|
||||
|
||||
return pcdata
|
||||
}
|
||||
|
||||
|
|
@ -232,7 +241,7 @@ func (ctxt *Link) EndUnsafePoint(p *Prog, newprog ProgAlloc, oldval int64) *Prog
|
|||
pcdata := Appendp(p, newprog)
|
||||
pcdata.As = APCDATA
|
||||
pcdata.From.Type = TYPE_CONST
|
||||
pcdata.From.Offset = objabi.PCDATA_StackMapIndex
|
||||
pcdata.From.Offset = objabi.PCDATA_RegMapIndex
|
||||
pcdata.To.Type = TYPE_CONST
|
||||
pcdata.To.Offset = oldval
|
||||
|
||||
|
|
@ -248,7 +257,7 @@ func MarkUnsafePoints(ctxt *Link, p0 *Prog, newprog ProgAlloc, isUnsafePoint fun
|
|||
prev := p0
|
||||
oldval := int64(-1) // entry pcdata
|
||||
for p := prev.Link; p != nil; p, prev = p.Link, p {
|
||||
if p.As == APCDATA && p.From.Offset == objabi.PCDATA_StackMapIndex {
|
||||
if p.As == APCDATA && p.From.Offset == objabi.PCDATA_RegMapIndex {
|
||||
oldval = p.To.Offset
|
||||
continue
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1045,6 +1045,12 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
var q *obj.Prog
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
|
|
@ -1153,7 +1159,7 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
q.Pcond = p
|
||||
}
|
||||
|
||||
p = c.ctxt.EmitEntryLiveness(c.cursym, p, c.newprog)
|
||||
p = c.ctxt.EmitEntryStackMap(c.cursym, p, c.newprog)
|
||||
|
||||
var morestacksym *obj.LSym
|
||||
if c.cursym.CFunc() {
|
||||
|
|
@ -1239,6 +1245,8 @@ func (c *ctxt9) stacksplit(p *obj.Prog, framesize int32) *obj.Prog {
|
|||
p.To.Reg = REG_R2
|
||||
}
|
||||
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
|
||||
// BR start
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
p.As = ABR
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ func rewriteMOV(ctxt *obj.Link, newprog obj.ProgAlloc, p *obj.Prog) {
|
|||
off := p.From.Offset
|
||||
to := p.To
|
||||
|
||||
low, high, err := split32BitImmediate(off)
|
||||
low, high, err := Split32BitImmediate(off)
|
||||
if err != nil {
|
||||
ctxt.Diag("%v: constant %d too large: %v", p, off, err)
|
||||
}
|
||||
|
|
@ -486,6 +486,116 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
}
|
||||
}
|
||||
|
||||
// Split immediates larger than 12-bits.
|
||||
for p := cursym.Func.Text; p != nil; p = p.Link {
|
||||
switch p.As {
|
||||
// <opi> $imm, REG, TO
|
||||
case AADDI, AANDI, AORI, AXORI:
|
||||
// LUI $high, TMP
|
||||
// ADDI $low, TMP, TMP
|
||||
// <op> TMP, REG, TO
|
||||
q := *p
|
||||
low, high, err := Split32BitImmediate(p.From.Offset)
|
||||
if err != nil {
|
||||
ctxt.Diag("%v: constant %d too large", p, p.From.Offset, err)
|
||||
}
|
||||
if high == 0 {
|
||||
break // no need to split
|
||||
}
|
||||
|
||||
p.As = ALUI
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
|
||||
p.Reg = 0
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p.Spadj = 0 // needed if TO is SP
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = AADDIW
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
|
||||
p.Reg = REG_TMP
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
switch q.As {
|
||||
case AADDI:
|
||||
p.As = AADD
|
||||
case AANDI:
|
||||
p.As = AAND
|
||||
case AORI:
|
||||
p.As = AOR
|
||||
case AXORI:
|
||||
p.As = AXOR
|
||||
default:
|
||||
ctxt.Diag("progedit: unsupported inst %v for splitting", q)
|
||||
}
|
||||
p.Spadj = q.Spadj
|
||||
p.To = q.To
|
||||
p.Reg = q.Reg
|
||||
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
|
||||
// <load> $imm, REG, TO (load $imm+(REG), TO)
|
||||
// <store> $imm, REG, TO (store $imm+(TO), REG)
|
||||
case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU,
|
||||
ASD, ASB, ASH, ASW:
|
||||
// LUI $high, TMP
|
||||
// ADDI $low, TMP, TMP
|
||||
q := *p
|
||||
low, high, err := Split32BitImmediate(p.From.Offset)
|
||||
if err != nil {
|
||||
ctxt.Diag("%v: constant %d too large", p, p.From.Offset)
|
||||
}
|
||||
if high == 0 {
|
||||
break // no need to split
|
||||
}
|
||||
|
||||
switch q.As {
|
||||
case ALD, ALB, ALH, ALW, ALBU, ALHU, ALWU:
|
||||
// LUI $high, TMP
|
||||
// ADD TMP, REG, TMP
|
||||
// <load> $low, TMP, TO
|
||||
p.As = ALUI
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
|
||||
p.Reg = 0
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p.Spadj = 0 // needed if TO is SP
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = AADD
|
||||
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p.Reg = q.Reg
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = q.As
|
||||
p.To = q.To
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
|
||||
p.Reg = REG_TMP
|
||||
|
||||
case ASD, ASB, ASH, ASW:
|
||||
// LUI $high, TMP
|
||||
// ADD TMP, TO, TMP
|
||||
// <store> $low, REG, TMP
|
||||
p.As = ALUI
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: high}
|
||||
p.Reg = 0
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p.Spadj = 0 // needed if TO is SP
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = AADD
|
||||
p.From = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p.Reg = q.To.Reg
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
||||
p.As = q.As
|
||||
p.Reg = q.Reg
|
||||
p.To = obj.Addr{Type: obj.TYPE_REG, Reg: REG_TMP}
|
||||
p.From = obj.Addr{Type: obj.TYPE_CONST, Offset: low}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setPCs(cursym.Func.Text, 0)
|
||||
|
||||
// Resolve branch and jump targets.
|
||||
|
|
@ -512,11 +622,11 @@ func signExtend(val int64, bit uint) int64 {
|
|||
return val << (64 - bit) >> (64 - bit)
|
||||
}
|
||||
|
||||
// split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
|
||||
// Split32BitImmediate splits a signed 32-bit immediate into a signed 20-bit
|
||||
// upper immediate and a signed 12-bit lower immediate to be added to the upper
|
||||
// result. For example, high may be used in LUI and low in a following ADDI to
|
||||
// generate a full 32-bit constant.
|
||||
func split32BitImmediate(imm int64) (low, high int64, err error) {
|
||||
func Split32BitImmediate(imm int64) (low, high int64, err error) {
|
||||
if !immIFits(imm, 32) {
|
||||
return 0, 0, fmt.Errorf("immediate does not fit in 32-bits: %d", imm)
|
||||
}
|
||||
|
|
@ -909,6 +1019,27 @@ func encodeRaw(p *obj.Prog) uint32 {
|
|||
return uint32(a.Offset)
|
||||
}
|
||||
|
||||
func EncodeIImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
}
|
||||
return imm << 20, nil
|
||||
}
|
||||
|
||||
func EncodeSImmediate(imm int64) (int64, error) {
|
||||
if !immIFits(imm, 12) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 12 bits", imm)
|
||||
}
|
||||
return ((imm >> 5) << 25) | ((imm & 0x1f) << 7), nil
|
||||
}
|
||||
|
||||
func EncodeUImmediate(imm int64) (int64, error) {
|
||||
if !immUFits(imm, 20) {
|
||||
return 0, fmt.Errorf("immediate %#x does not fit in 20 bits", imm)
|
||||
}
|
||||
return imm << 12, nil
|
||||
}
|
||||
|
||||
type encoding struct {
|
||||
encode func(*obj.Prog) uint32 // encode returns the machine code for an *obj.Prog
|
||||
validate func(*obj.Prog) // validate validates an *obj.Prog, calling ctxt.Diag for any issues
|
||||
|
|
|
|||
|
|
@ -335,6 +335,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
|
|||
if !p.From.Sym.NoSplit() {
|
||||
p, pPreempt = c.stacksplitPre(p, autosize) // emit pre part of split check
|
||||
pPre = p
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
wasSplit = true //need post part of split
|
||||
}
|
||||
|
||||
|
|
@ -575,15 +576,16 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro
|
|||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_R3
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = c.ctxt.StartUnsafePoint(p, c.newprog)
|
||||
|
||||
q = nil
|
||||
if framesize <= objabi.StackSmall {
|
||||
// small stack: SP < stackguard
|
||||
// CMP stackguard, SP
|
||||
|
||||
//p.To.Type = obj.TYPE_REG
|
||||
//p.To.Reg = REGSP
|
||||
|
||||
// q1: BLT done
|
||||
// CMPUBGE stackguard, SP, label-of-call-to-morestack
|
||||
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
//q1 = p
|
||||
|
|
@ -592,22 +594,11 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro
|
|||
p.Reg = REGSP
|
||||
p.As = ACMPUBGE
|
||||
p.To.Type = obj.TYPE_BRANCH
|
||||
//p = obj.Appendp(ctxt, p)
|
||||
|
||||
//p.As = ACMPU
|
||||
//p.From.Type = obj.TYPE_REG
|
||||
//p.From.Reg = REG_R3
|
||||
//p.To.Type = obj.TYPE_REG
|
||||
//p.To.Reg = REGSP
|
||||
|
||||
//p = obj.Appendp(ctxt, p)
|
||||
//p.As = ABGE
|
||||
//p.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
} else if framesize <= objabi.StackBig {
|
||||
// large stack: SP-framesize < stackguard-StackSmall
|
||||
// ADD $-(framesize-StackSmall), SP, R4
|
||||
// CMP stackguard, R4
|
||||
// CMPUBGE stackguard, R4, label-of-call-to-morestack
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = AADD
|
||||
|
|
@ -639,7 +630,7 @@ func (c *ctxtz) stacksplitPre(p *obj.Prog, framesize int32) (*obj.Prog, *obj.Pro
|
|||
// ADD $StackGuard, SP, R4
|
||||
// SUB R3, R4
|
||||
// MOVD $(framesize+(StackGuard-StackSmall)), TEMP
|
||||
// CMPUBGE TEMP, R4
|
||||
// CMPUBGE TEMP, R4, label-of-call-to-morestack
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
p.As = ACMP
|
||||
|
|
@ -694,7 +685,8 @@ func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog,
|
|||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := c.ctxt.EmitEntryLiveness(c.cursym, spfix, c.newprog)
|
||||
pcdata := c.ctxt.EmitEntryStackMap(c.cursym, spfix, c.newprog)
|
||||
pcdata = c.ctxt.StartUnsafePoint(pcdata, c.newprog)
|
||||
|
||||
// MOVD LR, R5
|
||||
p = obj.Appendp(pcdata, c.newprog)
|
||||
|
|
@ -721,6 +713,8 @@ func (c *ctxtz) stacksplitPost(p *obj.Prog, pPre *obj.Prog, pPreempt *obj.Prog,
|
|||
p.To.Sym = c.ctxt.Lookup("runtime.morestack")
|
||||
}
|
||||
|
||||
p = c.ctxt.EndUnsafePoint(p, c.newprog, -1)
|
||||
|
||||
// BR start
|
||||
p = obj.Appendp(p, c.newprog)
|
||||
|
||||
|
|
|
|||
|
|
@ -998,6 +998,12 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
if cursym.CFunc() {
|
||||
p.To.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
|
||||
}
|
||||
|
||||
// Mark the stack bound check and morestack call async nonpreemptible.
|
||||
// If we get preempted here, when resumed the preemption request is
|
||||
// cleared, but we'll still call morestack, which will double the stack
|
||||
// unnecessarily. See issue #35470.
|
||||
p = ctxt.StartUnsafePoint(p, newprog)
|
||||
} else if framesize <= objabi.StackBig {
|
||||
// large stack: SP-framesize <= stackguard-StackSmall
|
||||
// LEAQ -xxx(SP), AX
|
||||
|
|
@ -1020,6 +1026,8 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
if cursym.CFunc() {
|
||||
p.To.Offset = 3 * int64(ctxt.Arch.PtrSize) // G.stackguard1
|
||||
}
|
||||
|
||||
p = ctxt.StartUnsafePoint(p, newprog) // see the comment above
|
||||
} else {
|
||||
// Such a large stack we need to protect against wraparound.
|
||||
// If SP is close to zero:
|
||||
|
|
@ -1029,11 +1037,11 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
//
|
||||
// Preemption sets stackguard to StackPreempt, a very large value.
|
||||
// That breaks the math above, so we have to check for that explicitly.
|
||||
// MOVQ stackguard, CX
|
||||
// CMPQ CX, $StackPreempt
|
||||
// MOVQ stackguard, SI
|
||||
// CMPQ SI, $StackPreempt
|
||||
// JEQ label-of-call-to-morestack
|
||||
// LEAQ StackGuard(SP), AX
|
||||
// SUBQ CX, AX
|
||||
// SUBQ SI, AX
|
||||
// CMPQ AX, $(framesize+(StackGuard-StackSmall))
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
|
|
@ -1047,6 +1055,8 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
p.To.Type = obj.TYPE_REG
|
||||
p.To.Reg = REG_SI
|
||||
|
||||
p = ctxt.StartUnsafePoint(p, newprog) // see the comment above
|
||||
|
||||
p = obj.Appendp(p, newprog)
|
||||
p.As = cmp
|
||||
p.From.Type = obj.TYPE_REG
|
||||
|
|
@ -1090,6 +1100,8 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
jls.As = AJLS
|
||||
jls.To.Type = obj.TYPE_BRANCH
|
||||
|
||||
end := ctxt.EndUnsafePoint(jls, newprog, -1)
|
||||
|
||||
var last *obj.Prog
|
||||
for last = cursym.Func.Text; last.Link != nil; last = last.Link {
|
||||
}
|
||||
|
|
@ -1101,7 +1113,8 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
spfix.As = obj.ANOP
|
||||
spfix.Spadj = -framesize
|
||||
|
||||
pcdata := ctxt.EmitEntryLiveness(cursym, spfix, newprog)
|
||||
pcdata := ctxt.EmitEntryStackMap(cursym, spfix, newprog)
|
||||
pcdata = ctxt.StartUnsafePoint(pcdata, newprog)
|
||||
|
||||
call := obj.Appendp(pcdata, newprog)
|
||||
call.Pos = cursym.Func.Text.Pos
|
||||
|
|
@ -1126,7 +1139,9 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
progedit(ctxt, callend.Link, newprog)
|
||||
}
|
||||
|
||||
jmp := obj.Appendp(callend, newprog)
|
||||
pcdata = ctxt.EndUnsafePoint(callend, newprog, -1)
|
||||
|
||||
jmp := obj.Appendp(pcdata, newprog)
|
||||
jmp.As = obj.AJMP
|
||||
jmp.To.Type = obj.TYPE_BRANCH
|
||||
jmp.Pcond = cursym.Func.Text.Link
|
||||
|
|
@ -1137,7 +1152,7 @@ func stacksplit(ctxt *obj.Link, cursym *obj.LSym, p *obj.Prog, newprog obj.ProgA
|
|||
q1.Pcond = call
|
||||
}
|
||||
|
||||
return jls
|
||||
return end
|
||||
}
|
||||
|
||||
var unaryDst = map[obj.As]bool{
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ func (p XPos) WithIsStmt() XPos {
|
|||
// gdb chooses not to display the bogus line; delve shows it with a complaint, but the
|
||||
// alternative behavior is to hang.
|
||||
func (p XPos) WithBogusLine() XPos {
|
||||
if p.index == 0 {
|
||||
// See #35652
|
||||
panic("Assigning a bogus line to XPos with no file will cause mysterious downstream failures.")
|
||||
}
|
||||
p.lico = makeBogusLico()
|
||||
return p
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,3 +43,71 @@ func MustLinkExternal(goos, goarch string) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BuildModeSupported reports whether goos/goarch supports the given build mode
|
||||
// using the given compiler.
|
||||
func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
|
||||
if compiler == "gccgo" {
|
||||
return true
|
||||
}
|
||||
|
||||
platform := goos + "/" + goarch
|
||||
|
||||
switch buildmode {
|
||||
case "archive":
|
||||
return true
|
||||
|
||||
case "c-archive":
|
||||
// TODO(bcmills): This seems dubious.
|
||||
// Do we really support c-archive mode on js/wasm‽
|
||||
return platform != "linux/ppc64"
|
||||
|
||||
case "c-shared":
|
||||
switch platform {
|
||||
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/ppc64le", "linux/s390x",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"freebsd/amd64",
|
||||
"darwin/amd64", "darwin/386",
|
||||
"windows/amd64", "windows/386":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
case "default":
|
||||
return true
|
||||
|
||||
case "exe":
|
||||
return true
|
||||
|
||||
case "pie":
|
||||
switch platform {
|
||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"freebsd/amd64",
|
||||
"darwin/amd64",
|
||||
"aix/ppc64":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
case "shared":
|
||||
switch platform {
|
||||
case "linux/386", "linux/amd64", "linux/arm", "linux/arm64", "linux/ppc64le", "linux/s390x":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
case "plugin":
|
||||
switch platform {
|
||||
case "linux/amd64", "linux/arm", "linux/arm64", "linux/386", "linux/s390x", "linux/ppc64le",
|
||||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"darwin/amd64",
|
||||
"freebsd/amd64":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,38 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func getCCAndCCFLAGS(t *testing.T, env []string) (string, []string) {
|
||||
goTool := testenv.GoToolPath(t)
|
||||
cmd := exec.Command(goTool, "env", "CC")
|
||||
cmd.Env = env
|
||||
ccb, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cc := strings.TrimSpace(string(ccb))
|
||||
|
||||
cmd = exec.Command(goTool, "env", "GOGCCFLAGS")
|
||||
cmd.Env = env
|
||||
cflagsb, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cflags := strings.Fields(string(cflagsb))
|
||||
|
||||
return cc, cflags
|
||||
}
|
||||
|
||||
var asmSource = `
|
||||
.section .text1,"ax"
|
||||
s1:
|
||||
|
|
@ -61,21 +84,7 @@ func TestSectionsWithSameName(t *testing.T) {
|
|||
}
|
||||
|
||||
goTool := testenv.GoToolPath(t)
|
||||
cmd := exec.Command(goTool, "env", "CC")
|
||||
cmd.Env = env
|
||||
ccb, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cc := strings.TrimSpace(string(ccb))
|
||||
|
||||
cmd = exec.Command(goTool, "env", "GOGCCFLAGS")
|
||||
cmd.Env = env
|
||||
cflagsb, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cflags := strings.Fields(string(cflagsb))
|
||||
cc, cflags := getCCAndCCFLAGS(t, env)
|
||||
|
||||
asmObj := filepath.Join(dir, "x.o")
|
||||
t.Logf("%s %v -c -o %s %s", cc, cflags, asmObj, asmFile)
|
||||
|
|
@ -102,7 +111,7 @@ func TestSectionsWithSameName(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cmd = exec.Command(goTool, "build")
|
||||
cmd := exec.Command(goTool, "build")
|
||||
cmd.Dir = dir
|
||||
cmd.Env = env
|
||||
t.Logf("%s build", goTool)
|
||||
|
|
@ -111,3 +120,92 @@ func TestSectionsWithSameName(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
var cSources35779 = []string{`
|
||||
static int blah() { return 42; }
|
||||
int Cfunc1() { return blah(); }
|
||||
`, `
|
||||
static int blah() { return 42; }
|
||||
int Cfunc2() { return blah(); }
|
||||
`,
|
||||
}
|
||||
|
||||
// TestMinusRSymsWithSameName tests a corner case in the new
|
||||
// loader. Prior to the fix this failed with the error 'loadelf:
|
||||
// $WORK/b001/_pkg_.a(ldr.syso): duplicate symbol reference: blah in
|
||||
// both main(.text) and main(.text)'. See issue #35779.
|
||||
func TestMinusRSymsWithSameName(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
testenv.MustHaveCGO(t)
|
||||
t.Parallel()
|
||||
|
||||
// Skip this test on MIPS for the time being since it seems to trigger
|
||||
// problems with unknown relocations.
|
||||
if strings.Contains(runtime.GOARCH, "mips") {
|
||||
testenv.SkipFlaky(t, 35779)
|
||||
}
|
||||
|
||||
dir, err := ioutil.TempDir("", "go-link-TestMinusRSymsWithSameName")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
gopath := filepath.Join(dir, "GOPATH")
|
||||
env := append(os.Environ(), "GOPATH="+gopath)
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(dir, "go.mod"), []byte("module elf_test\n"), 0666); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
goTool := testenv.GoToolPath(t)
|
||||
cc, cflags := getCCAndCCFLAGS(t, env)
|
||||
|
||||
objs := []string{}
|
||||
csrcs := []string{}
|
||||
for i, content := range cSources35779 {
|
||||
csrcFile := filepath.Join(dir, fmt.Sprintf("x%d.c", i))
|
||||
csrcs = append(csrcs, csrcFile)
|
||||
if err := ioutil.WriteFile(csrcFile, []byte(content), 0444); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
obj := filepath.Join(dir, fmt.Sprintf("x%d.o", i))
|
||||
objs = append(objs, obj)
|
||||
t.Logf("%s %v -c -o %s %s", cc, cflags, obj, csrcFile)
|
||||
if out, err := exec.Command(cc, append(cflags, "-c", "-o", obj, csrcFile)...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
sysoObj := filepath.Join(dir, "ldr.syso")
|
||||
t.Logf("%s %v -nostdlib -r -o %s %v", cc, cflags, sysoObj, objs)
|
||||
if out, err := exec.Command(cc, append(cflags, "-nostdlib", "-r", "-o", sysoObj, objs[0], objs[1])...).CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
cruft := [][]string{objs, csrcs}
|
||||
for _, sl := range cruft {
|
||||
for _, s := range sl {
|
||||
if err := os.Remove(s); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
goFile := filepath.Join(dir, "main.go")
|
||||
if err := ioutil.WriteFile(goFile, []byte(goSource), 0444); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
t.Logf("%s build", goTool)
|
||||
cmd := exec.Command(goTool, "build")
|
||||
cmd.Dir = dir
|
||||
cmd.Env = env
|
||||
if out, err := cmd.CombinedOutput(); err != nil {
|
||||
t.Logf("%s", out)
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -462,6 +462,9 @@ func parseArmAttributes(e binary.ByteOrder, data []byte) (found bool, ehdrFlags
|
|||
// TODO: find a better place for this logic.
|
||||
func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string, initEhdrFlags uint32) (textp []*sym.Symbol, ehdrFlags uint32, err error) {
|
||||
localSymVersion := syms.IncVersion()
|
||||
newSym := func(name string, version int) *sym.Symbol {
|
||||
return l.Create(name, syms)
|
||||
}
|
||||
lookup := func(name string, version int) *sym.Symbol {
|
||||
return l.LookupOrCreate(name, version, syms)
|
||||
}
|
||||
|
|
@ -758,7 +761,7 @@ func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pk
|
|||
|
||||
for i := 1; i < elfobj.nsymtab; i++ {
|
||||
var elfsym ElfSym
|
||||
if err := readelfsym(lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
|
||||
if err := readelfsym(newSym, lookup, arch, elfobj, i, &elfsym, 1, localSymVersion); err != nil {
|
||||
return errorf("%s: malformed elf file: %v", pn, err)
|
||||
}
|
||||
symbols[i] = elfsym.sym
|
||||
|
|
@ -929,7 +932,7 @@ func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pk
|
|||
rp.Sym = nil
|
||||
} else {
|
||||
var elfsym ElfSym
|
||||
if err := readelfsym(lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
|
||||
if err := readelfsym(newSym, lookup, arch, elfobj, int(info>>32), &elfsym, 0, 0); err != nil {
|
||||
return errorf("malformed elf file: %v", err)
|
||||
}
|
||||
elfsym.sym = symbols[info>>32]
|
||||
|
|
@ -1006,7 +1009,7 @@ func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
|
|||
return nil
|
||||
}
|
||||
|
||||
func readelfsym(lookup func(string, int) *sym.Symbol, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
|
||||
func readelfsym(newSym, lookup func(string, int) *sym.Symbol, arch *sys.Arch, elfobj *ElfObj, i int, elfsym *ElfSym, needSym int, localSymVersion int) (err error) {
|
||||
if i >= elfobj.nsymtab || i < 0 {
|
||||
err = fmt.Errorf("invalid elf symbol index")
|
||||
return err
|
||||
|
|
@ -1092,7 +1095,10 @@ func readelfsym(lookup func(string, int) *sym.Symbol, arch *sys.Arch, elfobj *El
|
|||
// local names and hidden global names are unique
|
||||
// and should only be referenced by their index, not name, so we
|
||||
// don't bother to add them into the hash table
|
||||
s = lookup(elfsym.name, localSymVersion)
|
||||
// FIXME: pass empty string here for name? This would
|
||||
// reduce mem use, but also (possibly) make it harder
|
||||
// to debug problems.
|
||||
s = newSym(elfsym.name, localSymVersion)
|
||||
|
||||
s.Attr |= sym.AttrVisibilityHidden
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue