adding gox to tools package
This commit is contained in:
parent
9b41578d83
commit
7a471c0da7
1
go.mod
1
go.mod
|
@ -94,6 +94,7 @@ require (
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/mitchellh/go-linereader v0.0.0-20190213213312-1b945b3263eb
|
github.com/mitchellh/go-linereader v0.0.0-20190213213312-1b945b3263eb
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0
|
github.com/mitchellh/go-wordwrap v1.0.0
|
||||||
|
github.com/mitchellh/gox v1.0.1
|
||||||
github.com/mitchellh/hashstructure v1.0.0
|
github.com/mitchellh/hashstructure v1.0.0
|
||||||
github.com/mitchellh/mapstructure v1.1.2
|
github.com/mitchellh/mapstructure v1.1.2
|
||||||
github.com/mitchellh/panicwrap v1.0.0
|
github.com/mitchellh/panicwrap v1.0.0
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -81,8 +81,6 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbj
|
||||||
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
|
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
|
||||||
github.com/apparentlymart/go-userdirs v0.0.0-20190512014041-4a23807e62b9 h1:GRMI604e1ILyP9b5DTNAZFHx+Vu693kxb9ZBrIA2JQg=
|
github.com/apparentlymart/go-userdirs v0.0.0-20190512014041-4a23807e62b9 h1:GRMI604e1ILyP9b5DTNAZFHx+Vu693kxb9ZBrIA2JQg=
|
||||||
github.com/apparentlymart/go-userdirs v0.0.0-20190512014041-4a23807e62b9/go.mod h1:7kfpUbyCdGJ9fDRCp3fopPQi5+cKNHgTE4ZuNrO71Cw=
|
github.com/apparentlymart/go-userdirs v0.0.0-20190512014041-4a23807e62b9/go.mod h1:7kfpUbyCdGJ9fDRCp3fopPQi5+cKNHgTE4ZuNrO71Cw=
|
||||||
github.com/apparentlymart/go-versions v0.0.2-0.20180815153302-64b99f7cb171 h1:19Seu/H5gq3Ugtx+CGenwF89SDG3S1REX5i6PJj3RK4=
|
|
||||||
github.com/apparentlymart/go-versions v0.0.2-0.20180815153302-64b99f7cb171/go.mod h1:JXY95WvQrPJQtudvNARshgWajS7jNNlM90altXIPNyI=
|
|
||||||
github.com/apparentlymart/go-versions v1.0.0 h1:4A4CekGuwDUQqc+uTXCrdb9Y98JZsML2sdfNTeVjsK4=
|
github.com/apparentlymart/go-versions v1.0.0 h1:4A4CekGuwDUQqc+uTXCrdb9Y98JZsML2sdfNTeVjsK4=
|
||||||
github.com/apparentlymart/go-versions v1.0.0/go.mod h1:YF5j7IQtrOAOnsGkniupEA5bfCjzd7i14yu0shZavyM=
|
github.com/apparentlymart/go-versions v1.0.0/go.mod h1:YF5j7IQtrOAOnsGkniupEA5bfCjzd7i14yu0shZavyM=
|
||||||
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=
|
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 h1:7Ip0wMmLHLRJdrloDxZfhMm0xrLXZS8+COSu2bXmEQs=
|
||||||
|
@ -274,6 +272,7 @@ github.com/hashicorp/go-tfe v0.8.1/go.mod h1:XAV72S4O1iP8BDaqiaPLmL2B4EE6almocnO
|
||||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
||||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
|
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
|
@ -387,8 +386,12 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
|
github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
|
||||||
|
github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4=
|
||||||
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
|
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
|
||||||
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||||
|
github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
|
||||||
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
|
github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
|
||||||
|
|
|
@ -6,4 +6,5 @@ import (
|
||||||
_ "github.com/golang/mock/mockgen"
|
_ "github.com/golang/mock/mockgen"
|
||||||
_ "golang.org/x/tools/cmd/cover"
|
_ "golang.org/x/tools/cmd/cover"
|
||||||
_ "golang.org/x/tools/cmd/stringer"
|
_ "golang.org/x/tools/cmd/stringer"
|
||||||
|
_ "github.com/mitchellh/gox"
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
* text
|
|
@ -0,0 +1 @@
|
||||||
|
gox
|
|
@ -0,0 +1,15 @@
|
||||||
|
language: go
|
||||||
|
|
||||||
|
go:
|
||||||
|
- 1.6.x
|
||||||
|
- 1.7.x
|
||||||
|
- 1.8.x
|
||||||
|
- 1.9.x
|
||||||
|
- 1.10.x
|
||||||
|
- 1.11.x
|
||||||
|
- tip
|
||||||
|
|
||||||
|
script:
|
||||||
|
- go test ./...
|
||||||
|
|
||||||
|
go_import_path: github.com/mitchellh/gox
|
|
@ -0,0 +1,15 @@
|
||||||
|
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||||
|
|
||||||
|
|
||||||
|
[[projects]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/mitchellh/iochan"
|
||||||
|
packages = ["."]
|
||||||
|
revision = "87b45ffd0e9581375c491fef3d32130bb15c5bd7"
|
||||||
|
|
||||||
|
[solve-meta]
|
||||||
|
analyzer-name = "dep"
|
||||||
|
analyzer-version = 1
|
||||||
|
inputs-digest = "d7653d046a1e4d3471559a7d216e5a479923b8a706d83a6464e582a851ef2b98"
|
||||||
|
solver-name = "gps-cdcl"
|
||||||
|
solver-version = 1
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
# Gopkg.toml example
|
||||||
|
#
|
||||||
|
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
|
||||||
|
# for detailed Gopkg.toml documentation.
|
||||||
|
#
|
||||||
|
# required = ["github.com/user/thing/cmd/thing"]
|
||||||
|
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project"
|
||||||
|
# version = "1.0.0"
|
||||||
|
#
|
||||||
|
# [[constraint]]
|
||||||
|
# name = "github.com/user/project2"
|
||||||
|
# branch = "dev"
|
||||||
|
# source = "github.com/myfork/project2"
|
||||||
|
#
|
||||||
|
# [[override]]
|
||||||
|
# name = "github.com/x/y"
|
||||||
|
# version = "2.4.0"
|
||||||
|
|
||||||
|
|
||||||
|
[[constraint]]
|
||||||
|
branch = "master"
|
||||||
|
name = "github.com/mitchellh/iochan"
|
|
@ -0,0 +1,374 @@
|
||||||
|
Mozilla Public License Version 2.0
|
||||||
|
==================================
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
--------------
|
||||||
|
|
||||||
|
1.1. "Contributor"
|
||||||
|
means each individual or legal entity that creates, contributes to
|
||||||
|
the creation of, or owns Covered Software.
|
||||||
|
|
||||||
|
1.2. "Contributor Version"
|
||||||
|
means the combination of the Contributions of others (if any) used
|
||||||
|
by a Contributor and that particular Contributor's Contribution.
|
||||||
|
|
||||||
|
1.3. "Contribution"
|
||||||
|
means Covered Software of a particular Contributor.
|
||||||
|
|
||||||
|
1.4. "Covered Software"
|
||||||
|
means Source Code Form to which the initial Contributor has attached
|
||||||
|
the notice in Exhibit A, the Executable Form of such Source Code
|
||||||
|
Form, and Modifications of such Source Code Form, in each case
|
||||||
|
including portions thereof.
|
||||||
|
|
||||||
|
1.5. "Incompatible With Secondary Licenses"
|
||||||
|
means
|
||||||
|
|
||||||
|
(a) that the initial Contributor has attached the notice described
|
||||||
|
in Exhibit B to the Covered Software; or
|
||||||
|
|
||||||
|
(b) that the Covered Software was made available under the terms of
|
||||||
|
version 1.1 or earlier of the License, but not also under the
|
||||||
|
terms of a Secondary License.
|
||||||
|
|
||||||
|
1.6. "Executable Form"
|
||||||
|
means any form of the work other than Source Code Form.
|
||||||
|
|
||||||
|
1.7. "Larger Work"
|
||||||
|
means a work that combines Covered Software with other material, in
|
||||||
|
a separate file or files, that is not Covered Software.
|
||||||
|
|
||||||
|
1.8. "License"
|
||||||
|
means this document.
|
||||||
|
|
||||||
|
1.9. "Licensable"
|
||||||
|
means having the right to grant, to the maximum extent possible,
|
||||||
|
whether at the time of the initial grant or subsequently, any and
|
||||||
|
all of the rights conveyed by this License.
|
||||||
|
|
||||||
|
1.10. "Modifications"
|
||||||
|
means any of the following:
|
||||||
|
|
||||||
|
(a) any file in Source Code Form that results from an addition to,
|
||||||
|
deletion from, or modification of the contents of Covered
|
||||||
|
Software; or
|
||||||
|
|
||||||
|
(b) any new file in Source Code Form that contains any Covered
|
||||||
|
Software.
|
||||||
|
|
||||||
|
1.11. "Patent Claims" of a Contributor
|
||||||
|
means any patent claim(s), including without limitation, method,
|
||||||
|
process, and apparatus claims, in any patent Licensable by such
|
||||||
|
Contributor that would be infringed, but for the grant of the
|
||||||
|
License, by the making, using, selling, offering for sale, having
|
||||||
|
made, import, or transfer of either its Contributions or its
|
||||||
|
Contributor Version.
|
||||||
|
|
||||||
|
1.12. "Secondary License"
|
||||||
|
means either the GNU General Public License, Version 2.0, the GNU
|
||||||
|
Lesser General Public License, Version 2.1, the GNU Affero General
|
||||||
|
Public License, Version 3.0, or any later versions of those
|
||||||
|
licenses.
|
||||||
|
|
||||||
|
1.13. "Source Code Form"
|
||||||
|
means the form of the work preferred for making modifications.
|
||||||
|
|
||||||
|
1.14. "You" (or "Your")
|
||||||
|
means an individual or a legal entity exercising rights under this
|
||||||
|
License. For legal entities, "You" includes any entity that
|
||||||
|
controls, is controlled by, or is under common control with You. For
|
||||||
|
purposes of this definition, "control" means (a) the power, direct
|
||||||
|
or indirect, to cause the direction or management of such entity,
|
||||||
|
whether by contract or otherwise, or (b) ownership of more than
|
||||||
|
fifty percent (50%) of the outstanding shares or beneficial
|
||||||
|
ownership of such entity.
|
||||||
|
|
||||||
|
2. License Grants and Conditions
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
2.1. Grants
|
||||||
|
|
||||||
|
Each Contributor hereby grants You a world-wide, royalty-free,
|
||||||
|
non-exclusive license:
|
||||||
|
|
||||||
|
(a) under intellectual property rights (other than patent or trademark)
|
||||||
|
Licensable by such Contributor to use, reproduce, make available,
|
||||||
|
modify, display, perform, distribute, and otherwise exploit its
|
||||||
|
Contributions, either on an unmodified basis, with Modifications, or
|
||||||
|
as part of a Larger Work; and
|
||||||
|
|
||||||
|
(b) under Patent Claims of such Contributor to make, use, sell, offer
|
||||||
|
for sale, have made, import, and otherwise transfer either its
|
||||||
|
Contributions or its Contributor Version.
|
||||||
|
|
||||||
|
2.2. Effective Date
|
||||||
|
|
||||||
|
The licenses granted in Section 2.1 with respect to any Contribution
|
||||||
|
become effective for each Contribution on the date the Contributor first
|
||||||
|
distributes such Contribution.
|
||||||
|
|
||||||
|
2.3. Limitations on Grant Scope
|
||||||
|
|
||||||
|
The licenses granted in this Section 2 are the only rights granted under
|
||||||
|
this License. No additional rights or licenses will be implied from the
|
||||||
|
distribution or licensing of Covered Software under this License.
|
||||||
|
Notwithstanding Section 2.1(b) above, no patent license is granted by a
|
||||||
|
Contributor:
|
||||||
|
|
||||||
|
(a) for any code that a Contributor has removed from Covered Software;
|
||||||
|
or
|
||||||
|
|
||||||
|
(b) for infringements caused by: (i) Your and any other third party's
|
||||||
|
modifications of Covered Software, or (ii) the combination of its
|
||||||
|
Contributions with other software (except as part of its Contributor
|
||||||
|
Version); or
|
||||||
|
|
||||||
|
(c) under Patent Claims infringed by Covered Software in the absence of
|
||||||
|
its Contributions.
|
||||||
|
|
||||||
|
This License does not grant any rights in the trademarks, service marks,
|
||||||
|
or logos of any Contributor (except as may be necessary to comply with
|
||||||
|
the notice requirements in Section 3.4).
|
||||||
|
|
||||||
|
2.4. Subsequent Licenses
|
||||||
|
|
||||||
|
No Contributor makes additional grants as a result of Your choice to
|
||||||
|
distribute the Covered Software under a subsequent version of this
|
||||||
|
License (see Section 10.2) or under the terms of a Secondary License (if
|
||||||
|
permitted under the terms of Section 3.3).
|
||||||
|
|
||||||
|
2.5. Representation
|
||||||
|
|
||||||
|
Each Contributor represents that the Contributor believes its
|
||||||
|
Contributions are its original creation(s) or it has sufficient rights
|
||||||
|
to grant the rights to its Contributions conveyed by this License.
|
||||||
|
|
||||||
|
2.6. Fair Use
|
||||||
|
|
||||||
|
This License is not intended to limit any rights You have under
|
||||||
|
applicable copyright doctrines of fair use, fair dealing, or other
|
||||||
|
equivalents.
|
||||||
|
|
||||||
|
2.7. Conditions
|
||||||
|
|
||||||
|
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
|
||||||
|
in Section 2.1.
|
||||||
|
|
||||||
|
3. Responsibilities
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
3.1. Distribution of Source Form
|
||||||
|
|
||||||
|
All distribution of Covered Software in Source Code Form, including any
|
||||||
|
Modifications that You create or to which You contribute, must be under
|
||||||
|
the terms of this License. You must inform recipients that the Source
|
||||||
|
Code Form of the Covered Software is governed by the terms of this
|
||||||
|
License, and how they can obtain a copy of this License. You may not
|
||||||
|
attempt to alter or restrict the recipients' rights in the Source Code
|
||||||
|
Form.
|
||||||
|
|
||||||
|
3.2. Distribution of Executable Form
|
||||||
|
|
||||||
|
If You distribute Covered Software in Executable Form then:
|
||||||
|
|
||||||
|
(a) such Covered Software must also be made available in Source Code
|
||||||
|
Form, as described in Section 3.1, and You must inform recipients of
|
||||||
|
the Executable Form how they can obtain a copy of such Source Code
|
||||||
|
Form by reasonable means in a timely manner, at a charge no more
|
||||||
|
than the cost of distribution to the recipient; and
|
||||||
|
|
||||||
|
(b) You may distribute such Executable Form under the terms of this
|
||||||
|
License, or sublicense it under different terms, provided that the
|
||||||
|
license for the Executable Form does not attempt to limit or alter
|
||||||
|
the recipients' rights in the Source Code Form under this License.
|
||||||
|
|
||||||
|
3.3. Distribution of a Larger Work
|
||||||
|
|
||||||
|
You may create and distribute a Larger Work under terms of Your choice,
|
||||||
|
provided that You also comply with the requirements of this License for
|
||||||
|
the Covered Software. If the Larger Work is a combination of Covered
|
||||||
|
Software with a work governed by one or more Secondary Licenses, and the
|
||||||
|
Covered Software is not Incompatible With Secondary Licenses, this
|
||||||
|
License permits You to additionally distribute such Covered Software
|
||||||
|
under the terms of such Secondary License(s), so that the recipient of
|
||||||
|
the Larger Work may, at their option, further distribute the Covered
|
||||||
|
Software under the terms of either this License or such Secondary
|
||||||
|
License(s).
|
||||||
|
|
||||||
|
3.4. Notices
|
||||||
|
|
||||||
|
You may not remove or alter the substance of any license notices
|
||||||
|
(including copyright notices, patent notices, disclaimers of warranty,
|
||||||
|
or limitations of liability) contained within the Source Code Form of
|
||||||
|
the Covered Software, except that You may alter any license notices to
|
||||||
|
the extent required to remedy known factual inaccuracies.
|
||||||
|
|
||||||
|
3.5. Application of Additional Terms
|
||||||
|
|
||||||
|
You may choose to offer, and to charge a fee for, warranty, support,
|
||||||
|
indemnity or liability obligations to one or more recipients of Covered
|
||||||
|
Software. However, You may do so only on Your own behalf, and not on
|
||||||
|
behalf of any Contributor. You must make it absolutely clear that any
|
||||||
|
such warranty, support, indemnity, or liability obligation is offered by
|
||||||
|
You alone, and You hereby agree to indemnify every Contributor for any
|
||||||
|
liability incurred by such Contributor as a result of warranty, support,
|
||||||
|
indemnity or liability terms You offer. You may include additional
|
||||||
|
disclaimers of warranty and limitations of liability specific to any
|
||||||
|
jurisdiction.
|
||||||
|
|
||||||
|
4. Inability to Comply Due to Statute or Regulation
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
If it is impossible for You to comply with any of the terms of this
|
||||||
|
License with respect to some or all of the Covered Software due to
|
||||||
|
statute, judicial order, or regulation then You must: (a) comply with
|
||||||
|
the terms of this License to the maximum extent possible; and (b)
|
||||||
|
describe the limitations and the code they affect. Such description must
|
||||||
|
be placed in a text file included with all distributions of the Covered
|
||||||
|
Software under this License. Except to the extent prohibited by statute
|
||||||
|
or regulation, such description must be sufficiently detailed for a
|
||||||
|
recipient of ordinary skill to be able to understand it.
|
||||||
|
|
||||||
|
5. Termination
|
||||||
|
--------------
|
||||||
|
|
||||||
|
5.1. The rights granted under this License will terminate automatically
|
||||||
|
if You fail to comply with any of its terms. However, if You become
|
||||||
|
compliant, then the rights granted under this License from a particular
|
||||||
|
Contributor are reinstated (a) provisionally, unless and until such
|
||||||
|
Contributor explicitly and finally terminates Your grants, and (b) on an
|
||||||
|
ongoing basis, if such Contributor fails to notify You of the
|
||||||
|
non-compliance by some reasonable means prior to 60 days after You have
|
||||||
|
come back into compliance. Moreover, Your grants from a particular
|
||||||
|
Contributor are reinstated on an ongoing basis if such Contributor
|
||||||
|
notifies You of the non-compliance by some reasonable means, this is the
|
||||||
|
first time You have received notice of non-compliance with this License
|
||||||
|
from such Contributor, and You become compliant prior to 30 days after
|
||||||
|
Your receipt of the notice.
|
||||||
|
|
||||||
|
5.2. If You initiate litigation against any entity by asserting a patent
|
||||||
|
infringement claim (excluding declaratory judgment actions,
|
||||||
|
counter-claims, and cross-claims) alleging that a Contributor Version
|
||||||
|
directly or indirectly infringes any patent, then the rights granted to
|
||||||
|
You by any and all Contributors for the Covered Software under Section
|
||||||
|
2.1 of this License shall terminate.
|
||||||
|
|
||||||
|
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
|
||||||
|
end user license agreements (excluding distributors and resellers) which
|
||||||
|
have been validly granted by You or Your distributors under this License
|
||||||
|
prior to termination shall survive termination.
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
* *
|
||||||
|
* 6. Disclaimer of Warranty *
|
||||||
|
* ------------------------- *
|
||||||
|
* *
|
||||||
|
* Covered Software is provided under this License on an "as is" *
|
||||||
|
* basis, without warranty of any kind, either expressed, implied, or *
|
||||||
|
* statutory, including, without limitation, warranties that the *
|
||||||
|
* Covered Software is free of defects, merchantable, fit for a *
|
||||||
|
* particular purpose or non-infringing. The entire risk as to the *
|
||||||
|
* quality and performance of the Covered Software is with You. *
|
||||||
|
* Should any Covered Software prove defective in any respect, You *
|
||||||
|
* (not any Contributor) assume the cost of any necessary servicing, *
|
||||||
|
* repair, or correction. This disclaimer of warranty constitutes an *
|
||||||
|
* essential part of this License. No use of any Covered Software is *
|
||||||
|
* authorized under this License except under this disclaimer. *
|
||||||
|
* *
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
************************************************************************
|
||||||
|
* *
|
||||||
|
* 7. Limitation of Liability *
|
||||||
|
* -------------------------- *
|
||||||
|
* *
|
||||||
|
* Under no circumstances and under no legal theory, whether tort *
|
||||||
|
* (including negligence), contract, or otherwise, shall any *
|
||||||
|
* Contributor, or anyone who distributes Covered Software as *
|
||||||
|
* permitted above, be liable to You for any direct, indirect, *
|
||||||
|
* special, incidental, or consequential damages of any character *
|
||||||
|
* including, without limitation, damages for lost profits, loss of *
|
||||||
|
* goodwill, work stoppage, computer failure or malfunction, or any *
|
||||||
|
* and all other commercial damages or losses, even if such party *
|
||||||
|
* shall have been informed of the possibility of such damages. This *
|
||||||
|
* limitation of liability shall not apply to liability for death or *
|
||||||
|
* personal injury resulting from such party's negligence to the *
|
||||||
|
* extent applicable law prohibits such limitation. Some *
|
||||||
|
* jurisdictions do not allow the exclusion or limitation of *
|
||||||
|
* incidental or consequential damages, so this exclusion and *
|
||||||
|
* limitation may not apply to You. *
|
||||||
|
* *
|
||||||
|
************************************************************************
|
||||||
|
|
||||||
|
8. Litigation
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Any litigation relating to this License may be brought only in the
|
||||||
|
courts of a jurisdiction where the defendant maintains its principal
|
||||||
|
place of business and such litigation shall be governed by laws of that
|
||||||
|
jurisdiction, without reference to its conflict-of-law provisions.
|
||||||
|
Nothing in this Section shall prevent a party's ability to bring
|
||||||
|
cross-claims or counter-claims.
|
||||||
|
|
||||||
|
9. Miscellaneous
|
||||||
|
----------------
|
||||||
|
|
||||||
|
This License represents the complete agreement concerning the subject
|
||||||
|
matter hereof. If any provision of this License is held to be
|
||||||
|
unenforceable, such provision shall be reformed only to the extent
|
||||||
|
necessary to make it enforceable. Any law or regulation which provides
|
||||||
|
that the language of a contract shall be construed against the drafter
|
||||||
|
shall not be used to construe this License against a Contributor.
|
||||||
|
|
||||||
|
10. Versions of the License
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
10.1. New Versions
|
||||||
|
|
||||||
|
Mozilla Foundation is the license steward. Except as provided in Section
|
||||||
|
10.3, no one other than the license steward has the right to modify or
|
||||||
|
publish new versions of this License. Each version will be given a
|
||||||
|
distinguishing version number.
|
||||||
|
|
||||||
|
10.2. Effect of New Versions
|
||||||
|
|
||||||
|
You may distribute the Covered Software under the terms of the version
|
||||||
|
of the License under which You originally received the Covered Software,
|
||||||
|
or under the terms of any subsequent version published by the license
|
||||||
|
steward.
|
||||||
|
|
||||||
|
10.3. Modified Versions
|
||||||
|
|
||||||
|
If you create software not governed by this License, and you want to
|
||||||
|
create a new license for such software, you may create and use a
|
||||||
|
modified version of this License if you rename the license and remove
|
||||||
|
any references to the name of the license steward (except to note that
|
||||||
|
such modified license differs from this License).
|
||||||
|
|
||||||
|
10.4. Distributing Source Code Form that is Incompatible With Secondary
|
||||||
|
Licenses
|
||||||
|
|
||||||
|
If You choose to distribute Source Code Form that is Incompatible With
|
||||||
|
Secondary Licenses under the terms of this version of the License, the
|
||||||
|
notice described in Exhibit B of this License must be attached.
|
||||||
|
|
||||||
|
Exhibit A - Source Code Form License Notice
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
|
If it is not possible or desirable to put the notice in a particular
|
||||||
|
file, then You may include the notice in a location (such as a LICENSE
|
||||||
|
file in a relevant directory) where a recipient would be likely to look
|
||||||
|
for such a notice.
|
||||||
|
|
||||||
|
You may add additional accurate notices of copyright ownership.
|
||||||
|
|
||||||
|
Exhibit B - "Incompatible With Secondary Licenses" Notice
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
defined by the Mozilla Public License, v. 2.0.
|
||||||
|
|
|
@ -0,0 +1,95 @@
|
||||||
|
# Gox - Simple Go Cross Compilation
|
||||||
|
|
||||||
|
Gox is a simple, no-frills tool for Go cross compilation that behaves a
|
||||||
|
lot like standard `go build`. Gox will parallelize builds for multiple
|
||||||
|
platforms. Gox will also build the cross-compilation toolchain for you.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
To install Gox, please use `go get`. We tag versions so feel free to
|
||||||
|
checkout that tag and compile.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get github.com/mitchellh/gox
|
||||||
|
...
|
||||||
|
$ gox -h
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
If you know how to use `go build`, then you know how to use Gox. For
|
||||||
|
example, to build the current package, specify no parameters and just
|
||||||
|
call `gox`. Gox will parallelize based on the number of CPUs you have
|
||||||
|
by default and build for every platform by default:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gox
|
||||||
|
Number of parallel builds: 4
|
||||||
|
|
||||||
|
--> darwin/386: github.com/mitchellh/gox
|
||||||
|
--> darwin/amd64: github.com/mitchellh/gox
|
||||||
|
--> linux/386: github.com/mitchellh/gox
|
||||||
|
--> linux/amd64: github.com/mitchellh/gox
|
||||||
|
--> linux/arm: github.com/mitchellh/gox
|
||||||
|
--> freebsd/386: github.com/mitchellh/gox
|
||||||
|
--> freebsd/amd64: github.com/mitchellh/gox
|
||||||
|
--> openbsd/386: github.com/mitchellh/gox
|
||||||
|
--> openbsd/amd64: github.com/mitchellh/gox
|
||||||
|
--> windows/386: github.com/mitchellh/gox
|
||||||
|
--> windows/amd64: github.com/mitchellh/gox
|
||||||
|
--> freebsd/arm: github.com/mitchellh/gox
|
||||||
|
--> netbsd/386: github.com/mitchellh/gox
|
||||||
|
--> netbsd/amd64: github.com/mitchellh/gox
|
||||||
|
--> netbsd/arm: github.com/mitchellh/gox
|
||||||
|
--> plan9/386: github.com/mitchellh/gox
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you want to build a package and sub-packages:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gox ./...
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, if you want to build multiple distinct packages:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gox github.com/mitchellh/gox github.com/hashicorp/serf
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Or if you want to just build for linux:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gox -os="linux"
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Or maybe you just want to build for 64-bit linux:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ gox -osarch="linux/amd64"
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
And more! Just run `gox -h` for help and additional information.
|
||||||
|
|
||||||
|
## Versus Other Cross-Compile Tools
|
||||||
|
|
||||||
|
A big thanks to these other options for existing. They each paved the
|
||||||
|
way in many aspects to make Go cross-compilation approachable.
|
||||||
|
|
||||||
|
* [Dave Cheney's golang-crosscompile](https://github.com/davecheney/golang-crosscompile) -
|
||||||
|
Gox compiles for multiple platforms and can therefore easily run on
|
||||||
|
any platform Go supports, whereas Dave's scripts require a shell. Gox
|
||||||
|
will also parallelize builds. Dave's scripts build sequentially. Gox has
|
||||||
|
much easier to use OS/Arch filtering built in.
|
||||||
|
|
||||||
|
* [goxc](https://github.com/laher/goxc) -
|
||||||
|
A very richly featured tool that can even do things such as build system
|
||||||
|
packages, upload binaries, generate download webpages, etc. Gox is a
|
||||||
|
super slim alternative that only cross-compiles binaries. Gox builds packages in parallel, whereas
|
||||||
|
goxc doesn't. Gox doesn't enforce a specific output structure for built
|
||||||
|
binaries.
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
|
||||||
|
version: build-{build}.{branch}
|
||||||
|
|
||||||
|
clone_folder: C:\gopath\src\github.com\mitchellh\gox
|
||||||
|
shallow_clone: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
GOPATH: C:\gopath
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- x64
|
||||||
|
|
||||||
|
test_script:
|
||||||
|
- go get ./...
|
||||||
|
- go test -v ./...
|
||||||
|
|
||||||
|
build: off
|
||||||
|
|
||||||
|
deploy: off
|
|
@ -0,0 +1,17 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// envOverride overrides the given target based on if there is a
|
||||||
|
// env var in the format of GOX_{OS}_{ARCH}_{KEY}.
|
||||||
|
func envOverride(target *string, platform Platform, key string) {
|
||||||
|
key = strings.ToUpper(fmt.Sprintf(
|
||||||
|
"GOX_%s_%s_%s", platform.OS, platform.Arch, key))
|
||||||
|
if v := os.Getenv(key); v != "" {
|
||||||
|
*target = v
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,233 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"text/template"
|
||||||
|
)
|
||||||
|
|
||||||
|
type OutputTemplateData struct {
|
||||||
|
Dir string
|
||||||
|
OS string
|
||||||
|
Arch string
|
||||||
|
}
|
||||||
|
|
||||||
|
type CompileOpts struct {
|
||||||
|
PackagePath string
|
||||||
|
Platform Platform
|
||||||
|
OutputTpl string
|
||||||
|
Ldflags string
|
||||||
|
Gcflags string
|
||||||
|
Asmflags string
|
||||||
|
Tags string
|
||||||
|
ModMode string
|
||||||
|
Cgo bool
|
||||||
|
Rebuild bool
|
||||||
|
GoCmd string
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoCrossCompile
|
||||||
|
func GoCrossCompile(opts *CompileOpts) error {
|
||||||
|
env := append(os.Environ(),
|
||||||
|
"GOOS="+opts.Platform.OS,
|
||||||
|
"GOARCH="+opts.Platform.Arch)
|
||||||
|
|
||||||
|
// If we're building for our own platform, then enable cgo always. We
|
||||||
|
// respect the CGO_ENABLED flag if that is explicitly set on the platform.
|
||||||
|
if !opts.Cgo && os.Getenv("CGO_ENABLED") != "0" {
|
||||||
|
opts.Cgo = runtime.GOOS == opts.Platform.OS &&
|
||||||
|
runtime.GOARCH == opts.Platform.Arch
|
||||||
|
}
|
||||||
|
|
||||||
|
// If cgo is enabled then set that env var
|
||||||
|
if opts.Cgo {
|
||||||
|
env = append(env, "CGO_ENABLED=1")
|
||||||
|
} else {
|
||||||
|
env = append(env, "CGO_ENABLED=0")
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputPath bytes.Buffer
|
||||||
|
tpl, err := template.New("output").Parse(opts.OutputTpl)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
tplData := OutputTemplateData{
|
||||||
|
Dir: filepath.Base(opts.PackagePath),
|
||||||
|
OS: opts.Platform.OS,
|
||||||
|
Arch: opts.Platform.Arch,
|
||||||
|
}
|
||||||
|
if err := tpl.Execute(&outputPath, &tplData); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.Platform.OS == "windows" {
|
||||||
|
outputPath.WriteString(".exe")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the full path to the output so that we can change our
|
||||||
|
// working directory when executing go build.
|
||||||
|
outputPathReal := outputPath.String()
|
||||||
|
outputPathReal, err = filepath.Abs(outputPathReal)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go prefixes the import directory with '_' when it is outside
|
||||||
|
// the GOPATH.For this, we just drop it since we move to that
|
||||||
|
// directory to build.
|
||||||
|
chdir := ""
|
||||||
|
if opts.PackagePath[0] == '_' {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
// We have to replace weird paths like this:
|
||||||
|
//
|
||||||
|
// _/c_/Users
|
||||||
|
//
|
||||||
|
// With:
|
||||||
|
//
|
||||||
|
// c:\Users
|
||||||
|
//
|
||||||
|
re := regexp.MustCompile("^/([a-zA-Z])_/")
|
||||||
|
chdir = re.ReplaceAllString(opts.PackagePath[1:], "$1:\\")
|
||||||
|
chdir = strings.Replace(chdir, "/", "\\", -1)
|
||||||
|
} else {
|
||||||
|
chdir = opts.PackagePath[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
opts.PackagePath = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
args := []string{"build"}
|
||||||
|
if opts.Rebuild {
|
||||||
|
args = append(args, "-a")
|
||||||
|
}
|
||||||
|
if opts.ModMode != "" {
|
||||||
|
args = append(args, "-mod", opts.ModMode)
|
||||||
|
}
|
||||||
|
args = append(args,
|
||||||
|
"-gcflags", opts.Gcflags,
|
||||||
|
"-ldflags", opts.Ldflags,
|
||||||
|
"-asmflags", opts.Asmflags,
|
||||||
|
"-tags", opts.Tags,
|
||||||
|
"-o", outputPathReal,
|
||||||
|
opts.PackagePath)
|
||||||
|
|
||||||
|
_, err = execGo(opts.GoCmd, env, chdir, args...)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoMainDirs returns the file paths to the packages that are "main"
|
||||||
|
// packages, from the list of packages given. The list of packages can
|
||||||
|
// include relative paths, the special "..." Go keyword, etc.
|
||||||
|
func GoMainDirs(packages []string, GoCmd string) ([]string, error) {
|
||||||
|
args := make([]string, 0, len(packages)+3)
|
||||||
|
args = append(args, "list", "-f", "{{.Name}}|{{.ImportPath}}")
|
||||||
|
args = append(args, packages...)
|
||||||
|
|
||||||
|
output, err := execGo(GoCmd, nil, "", args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
results := make([]string, 0, len(output))
|
||||||
|
for _, line := range strings.Split(output, "\n") {
|
||||||
|
if line == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
parts := strings.SplitN(line, "|", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
log.Printf("Bad line reading packages: %s", line)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if parts[0] == "main" {
|
||||||
|
results = append(results, parts[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoRoot returns the GOROOT value for the compiled `go` binary.
|
||||||
|
func GoRoot() (string, error) {
|
||||||
|
output, err := execGo("go", nil, "", "env", "GOROOT")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(output), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoVersion reads the version of `go` that is on the PATH. This is done
|
||||||
|
// instead of `runtime.Version()` because it is possible to run gox against
|
||||||
|
// another Go version.
|
||||||
|
func GoVersion() (string, error) {
|
||||||
|
// NOTE: We use `go run` instead of `go version` because the output
|
||||||
|
// of `go version` might change whereas the source is guaranteed to run
|
||||||
|
// for some time thanks to Go's compatibility guarantee.
|
||||||
|
|
||||||
|
td, err := ioutil.TempDir("", "gox")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(td)
|
||||||
|
|
||||||
|
// Write the source code for the program that will generate the version
|
||||||
|
sourcePath := filepath.Join(td, "version.go")
|
||||||
|
if err := ioutil.WriteFile(sourcePath, []byte(versionSource), 0644); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute and read the version, which will be the only thing on stdout.
|
||||||
|
return execGo("go", nil, "", "run", sourcePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GoVersionParts parses the version numbers from the version itself
|
||||||
|
// into major and minor: 1.5, 1.4, etc.
|
||||||
|
func GoVersionParts() (result [2]int, err error) {
|
||||||
|
version, err := GoVersion()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = fmt.Sscanf(version, "go%d.%d", &result[0], &result[1])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func execGo(GoCmd string, env []string, dir string, args ...string) (string, error) {
|
||||||
|
var stderr, stdout bytes.Buffer
|
||||||
|
cmd := exec.Command(GoCmd, args...)
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
if env != nil {
|
||||||
|
cmd.Env = env
|
||||||
|
}
|
||||||
|
if dir != "" {
|
||||||
|
cmd.Dir = dir
|
||||||
|
}
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
err = fmt.Errorf("%s\nStderr: %s", err, stderr.String())
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return stdout.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const versionSource = `package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
fmt.Print(runtime.Version())
|
||||||
|
}`
|
|
@ -0,0 +1,6 @@
|
||||||
|
module github.com/mitchellh/gox
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/hashicorp/go-version v1.0.0
|
||||||
|
github.com/mitchellh/iochan v1.0.0
|
||||||
|
)
|
|
@ -0,0 +1,6 @@
|
||||||
|
github.com/hashicorp/go-version v1.0.0 h1:21MVWPKDphxa7ineQQTrCU5brh7OuVVAzGOCnnCPtE8=
|
||||||
|
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
|
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95 h1:aHWVygBsLb+Kls/35B3tevL1hvDxZ0UklPA0BmhqTEk=
|
||||||
|
github.com/mitchellh/iochan v0.0.0-20150529224432-87b45ffd0e95/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
|
github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
|
||||||
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
|
@ -0,0 +1,262 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
version "github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Call realMain so that defers work properly, since os.Exit won't
|
||||||
|
// call defers.
|
||||||
|
os.Exit(realMain())
|
||||||
|
}
|
||||||
|
|
||||||
|
func realMain() int {
|
||||||
|
var buildToolchain bool
|
||||||
|
var ldflags string
|
||||||
|
var outputTpl string
|
||||||
|
var parallel int
|
||||||
|
var platformFlag PlatformFlag
|
||||||
|
var tags string
|
||||||
|
var verbose bool
|
||||||
|
var flagGcflags, flagAsmflags string
|
||||||
|
var flagCgo, flagRebuild, flagListOSArch bool
|
||||||
|
var flagGoCmd string
|
||||||
|
var modMode string
|
||||||
|
flags := flag.NewFlagSet("gox", flag.ExitOnError)
|
||||||
|
flags.Usage = func() { printUsage() }
|
||||||
|
flags.Var(platformFlag.ArchFlagValue(), "arch", "arch to build for or skip")
|
||||||
|
flags.Var(platformFlag.OSArchFlagValue(), "osarch", "os/arch pairs to build for or skip")
|
||||||
|
flags.Var(platformFlag.OSFlagValue(), "os", "os to build for or skip")
|
||||||
|
flags.StringVar(&ldflags, "ldflags", "", "linker flags")
|
||||||
|
flags.StringVar(&tags, "tags", "", "go build tags")
|
||||||
|
flags.StringVar(&outputTpl, "output", "{{.Dir}}_{{.OS}}_{{.Arch}}", "output path")
|
||||||
|
flags.IntVar(¶llel, "parallel", -1, "parallelization factor")
|
||||||
|
flags.BoolVar(&buildToolchain, "build-toolchain", false, "build toolchain")
|
||||||
|
flags.BoolVar(&verbose, "verbose", false, "verbose")
|
||||||
|
flags.BoolVar(&flagCgo, "cgo", false, "")
|
||||||
|
flags.BoolVar(&flagRebuild, "rebuild", false, "")
|
||||||
|
flags.BoolVar(&flagListOSArch, "osarch-list", false, "")
|
||||||
|
flags.StringVar(&flagGcflags, "gcflags", "", "")
|
||||||
|
flags.StringVar(&flagAsmflags, "asmflags", "", "")
|
||||||
|
flags.StringVar(&flagGoCmd, "gocmd", "go", "")
|
||||||
|
flags.StringVar(&modMode, "mod", "", "")
|
||||||
|
if err := flags.Parse(os.Args[1:]); err != nil {
|
||||||
|
flags.Usage()
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine what amount of parallelism we want Default to the current
|
||||||
|
// number of CPUs-1 is <= 0 is specified.
|
||||||
|
if parallel <= 0 {
|
||||||
|
cpus := runtime.NumCPU()
|
||||||
|
if cpus < 2 {
|
||||||
|
parallel = 1
|
||||||
|
} else {
|
||||||
|
parallel = cpus - 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Joyent containers report 48 cores via runtime.NumCPU(), and a
|
||||||
|
// default of 47 parallel builds causes a panic. Default to 3 on
|
||||||
|
// Solaris-derived operating systems unless overridden with the
|
||||||
|
// -parallel flag.
|
||||||
|
if runtime.GOOS == "solaris" {
|
||||||
|
parallel = 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buildToolchain {
|
||||||
|
return mainBuildToolchain(parallel, platformFlag, verbose)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := exec.LookPath(flagGoCmd); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s executable must be on the PATH\n",
|
||||||
|
flagGoCmd)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
versionStr, err := GoVersion()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error reading Go version: %s", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if flagListOSArch {
|
||||||
|
return mainListOSArch(versionStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the packages that we want to compile. Default to the
|
||||||
|
// current directory if none are specified.
|
||||||
|
packages := flags.Args()
|
||||||
|
if len(packages) == 0 {
|
||||||
|
packages = []string{"."}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the packages that are in the given paths
|
||||||
|
mainDirs, err := GoMainDirs(packages, flagGoCmd)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error reading packages: %s", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the platforms we're building for
|
||||||
|
platforms := platformFlag.Platforms(SupportedPlatforms(versionStr))
|
||||||
|
if len(platforms) == 0 {
|
||||||
|
fmt.Println("No valid platforms to build for. If you specified a value")
|
||||||
|
fmt.Println("for the 'os', 'arch', or 'osarch' flags, make sure you're")
|
||||||
|
fmt.Println("using a valid value.")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume -mod is supported when no version prefix is found
|
||||||
|
if modMode != "" && strings.HasPrefix(versionStr, "go") {
|
||||||
|
// go-version only cares about version numbers
|
||||||
|
current, err := version.NewVersion(versionStr[2:])
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Unable to parse current go version: %s\n%s", versionStr, err.Error())
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint, err := version.NewConstraint(">= 1.11")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !constraint.Check(current) {
|
||||||
|
fmt.Printf("Go compiler version %s does not support the -mod flag\n", versionStr)
|
||||||
|
modMode = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build in parallel!
|
||||||
|
fmt.Printf("Number of parallel builds: %d\n\n", parallel)
|
||||||
|
var errorLock sync.Mutex
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
errors := make([]string, 0)
|
||||||
|
semaphore := make(chan int, parallel)
|
||||||
|
for _, platform := range platforms {
|
||||||
|
for _, path := range mainDirs {
|
||||||
|
// Start the goroutine that will do the actual build
|
||||||
|
wg.Add(1)
|
||||||
|
go func(path string, platform Platform) {
|
||||||
|
defer wg.Done()
|
||||||
|
semaphore <- 1
|
||||||
|
fmt.Printf("--> %15s: %s\n", platform.String(), path)
|
||||||
|
|
||||||
|
opts := &CompileOpts{
|
||||||
|
PackagePath: path,
|
||||||
|
Platform: platform,
|
||||||
|
OutputTpl: outputTpl,
|
||||||
|
Ldflags: ldflags,
|
||||||
|
Gcflags: flagGcflags,
|
||||||
|
Asmflags: flagAsmflags,
|
||||||
|
Tags: tags,
|
||||||
|
ModMode: modMode,
|
||||||
|
Cgo: flagCgo,
|
||||||
|
Rebuild: flagRebuild,
|
||||||
|
GoCmd: flagGoCmd,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine if we have specific CFLAGS or LDFLAGS for this
|
||||||
|
// GOOS/GOARCH combo and override the defaults if so.
|
||||||
|
envOverride(&opts.Ldflags, platform, "LDFLAGS")
|
||||||
|
envOverride(&opts.Gcflags, platform, "GCFLAGS")
|
||||||
|
envOverride(&opts.Asmflags, platform, "ASMFLAGS")
|
||||||
|
|
||||||
|
if err := GoCrossCompile(opts); err != nil {
|
||||||
|
errorLock.Lock()
|
||||||
|
defer errorLock.Unlock()
|
||||||
|
errors = append(errors,
|
||||||
|
fmt.Sprintf("%s error: %s", platform.String(), err))
|
||||||
|
}
|
||||||
|
<-semaphore
|
||||||
|
}(path, platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if len(errors) > 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "\n%d errors occurred:\n", len(errors))
|
||||||
|
for _, err := range errors {
|
||||||
|
fmt.Fprintf(os.Stderr, "--> %s\n", err)
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func printUsage() {
|
||||||
|
fmt.Fprintf(os.Stderr, helpText)
|
||||||
|
}
|
||||||
|
|
||||||
|
const helpText = `Usage: gox [options] [packages]
|
||||||
|
|
||||||
|
Gox cross-compiles Go applications in parallel.
|
||||||
|
|
||||||
|
If no specific operating systems or architectures are specified, Gox
|
||||||
|
will build for all pairs supported by your version of Go.
|
||||||
|
|
||||||
|
Options:
|
||||||
|
|
||||||
|
-arch="" Space-separated list of architectures to build for
|
||||||
|
-build-toolchain Build cross-compilation toolchain
|
||||||
|
-cgo Sets CGO_ENABLED=1, requires proper C toolchain (advanced)
|
||||||
|
-gcflags="" Additional '-gcflags' value to pass to go build
|
||||||
|
-ldflags="" Additional '-ldflags' value to pass to go build
|
||||||
|
-asmflags="" Additional '-asmflags' value to pass to go build
|
||||||
|
-tags="" Additional '-tags' value to pass to go build
|
||||||
|
-mod="" Additional '-mod' value to pass to go build
|
||||||
|
-os="" Space-separated list of operating systems to build for
|
||||||
|
-osarch="" Space-separated list of os/arch pairs to build for
|
||||||
|
-osarch-list List supported os/arch pairs for your Go version
|
||||||
|
-output="foo" Output path template. See below for more info
|
||||||
|
-parallel=-1 Amount of parallelism, defaults to number of CPUs
|
||||||
|
-gocmd="go" Build command, defaults to Go
|
||||||
|
-rebuild Force rebuilding of package that were up to date
|
||||||
|
-verbose Verbose mode
|
||||||
|
|
||||||
|
Output path template:
|
||||||
|
|
||||||
|
The output path for the compiled binaries is specified with the
|
||||||
|
"-output" flag. The value is a string that is a Go text template.
|
||||||
|
The default value is "{{.Dir}}_{{.OS}}_{{.Arch}}". The variables and
|
||||||
|
their values should be self-explanatory.
|
||||||
|
|
||||||
|
Platforms (OS/Arch):
|
||||||
|
|
||||||
|
The operating systems and architectures to cross-compile for may be
|
||||||
|
specified with the "-arch" and "-os" flags. These are space separated lists
|
||||||
|
of valid GOOS/GOARCH values to build for, respectively. You may prefix an
|
||||||
|
OS or Arch with "!" to negate and not build for that platform. If the list
|
||||||
|
is made up of only negations, then the negations will come from the default
|
||||||
|
list.
|
||||||
|
|
||||||
|
Additionally, the "-osarch" flag may be used to specify complete os/arch
|
||||||
|
pairs that should be built or ignored. The syntax for this is what you would
|
||||||
|
expect: "darwin/amd64" would be a valid osarch value. Multiple can be space
|
||||||
|
separated. An os/arch pair can begin with "!" to not build for that platform.
|
||||||
|
|
||||||
|
The "-osarch" flag has the highest precedent when determing whether to
|
||||||
|
build for a platform. If it is included in the "-osarch" list, it will be
|
||||||
|
built even if the specific os and arch is negated in "-os" and "-arch",
|
||||||
|
respectively.
|
||||||
|
|
||||||
|
Platform Overrides:
|
||||||
|
|
||||||
|
The "-gcflags", "-ldflags" and "-asmflags" options can be overridden per-platform
|
||||||
|
by using environment variables. Gox will look for environment variables
|
||||||
|
in the following format and use those to override values if they exist:
|
||||||
|
|
||||||
|
GOX_[OS]_[ARCH]_GCFLAGS
|
||||||
|
GOX_[OS]_[ARCH]_LDFLAGS
|
||||||
|
GOX_[OS]_[ARCH]_ASMFLAGS
|
||||||
|
|
||||||
|
`
|
|
@ -0,0 +1,19 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func mainListOSArch(version string) int {
|
||||||
|
fmt.Printf(
|
||||||
|
"Supported OS/Arch combinations for %s are shown below. The \"default\"\n"+
|
||||||
|
"boolean means that if you don't specify an OS/Arch, it will be\n"+
|
||||||
|
"included by default. If it isn't a default OS/Arch, you must explicitly\n"+
|
||||||
|
"specify that OS/Arch combo for Gox to use it.\n\n",
|
||||||
|
version)
|
||||||
|
for _, p := range SupportedPlatforms(version) {
|
||||||
|
fmt.Printf("%s\t(default: %v)\n", p.String(), p.Default)
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
version "github.com/hashicorp/go-version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Platform is a combination of OS/arch that can be built against.
|
||||||
|
type Platform struct {
|
||||||
|
OS string
|
||||||
|
Arch string
|
||||||
|
|
||||||
|
// Default, if true, will be included as a default build target
|
||||||
|
// if no OS/arch is specified. We try to only set as a default popular
|
||||||
|
// targets or targets that are generally useful. For example, Android
|
||||||
|
// is not a default because it is quite rare that you're cross-compiling
|
||||||
|
// something to Android AND something like Linux.
|
||||||
|
Default bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Platform) String() string {
|
||||||
|
return fmt.Sprintf("%s/%s", p.OS, p.Arch)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Platforms_1_0 = []Platform{
|
||||||
|
{"darwin", "386", true},
|
||||||
|
{"darwin", "amd64", true},
|
||||||
|
{"linux", "386", true},
|
||||||
|
{"linux", "amd64", true},
|
||||||
|
{"linux", "arm", true},
|
||||||
|
{"freebsd", "386", true},
|
||||||
|
{"freebsd", "amd64", true},
|
||||||
|
{"openbsd", "386", true},
|
||||||
|
{"openbsd", "amd64", true},
|
||||||
|
{"windows", "386", true},
|
||||||
|
{"windows", "amd64", true},
|
||||||
|
}
|
||||||
|
|
||||||
|
Platforms_1_1 = append(Platforms_1_0, []Platform{
|
||||||
|
{"freebsd", "arm", true},
|
||||||
|
{"netbsd", "386", true},
|
||||||
|
{"netbsd", "amd64", true},
|
||||||
|
{"netbsd", "arm", true},
|
||||||
|
{"plan9", "386", false},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
Platforms_1_3 = append(Platforms_1_1, []Platform{
|
||||||
|
{"dragonfly", "386", false},
|
||||||
|
{"dragonfly", "amd64", false},
|
||||||
|
{"nacl", "amd64", false},
|
||||||
|
{"nacl", "amd64p32", false},
|
||||||
|
{"nacl", "arm", false},
|
||||||
|
{"solaris", "amd64", false},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
Platforms_1_4 = append(Platforms_1_3, []Platform{
|
||||||
|
{"android", "arm", false},
|
||||||
|
{"plan9", "amd64", false},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
Platforms_1_5 = append(Platforms_1_4, []Platform{
|
||||||
|
{"darwin", "arm", false},
|
||||||
|
{"darwin", "arm64", false},
|
||||||
|
{"linux", "arm64", false},
|
||||||
|
{"linux", "ppc64", false},
|
||||||
|
{"linux", "ppc64le", false},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
Platforms_1_6 = append(Platforms_1_5, []Platform{
|
||||||
|
{"android", "386", false},
|
||||||
|
{"linux", "mips64", false},
|
||||||
|
{"linux", "mips64le", false},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
Platforms_1_7 = append(Platforms_1_5, []Platform{
|
||||||
|
// While not fully supported s390x is generally useful
|
||||||
|
{"linux", "s390x", true},
|
||||||
|
{"plan9", "arm", false},
|
||||||
|
// Add the 1.6 Platforms, but reflect full support for mips64 and mips64le
|
||||||
|
{"android", "386", false},
|
||||||
|
{"linux", "mips64", true},
|
||||||
|
{"linux", "mips64le", true},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
Platforms_1_8 = append(Platforms_1_7, []Platform{
|
||||||
|
{"linux", "mips", true},
|
||||||
|
{"linux", "mipsle", true},
|
||||||
|
}...)
|
||||||
|
|
||||||
|
// no new platforms in 1.9
|
||||||
|
Platforms_1_9 = Platforms_1_8
|
||||||
|
|
||||||
|
// no new platforms in 1.10
|
||||||
|
Platforms_1_10 = Platforms_1_9
|
||||||
|
|
||||||
|
PlatformsLatest = Platforms_1_10
|
||||||
|
)
|
||||||
|
|
||||||
|
// SupportedPlatforms returns the full list of supported platforms for
|
||||||
|
// the version of Go that is
|
||||||
|
func SupportedPlatforms(v string) []Platform {
|
||||||
|
// Use latest if we get an unexpected version string
|
||||||
|
if !strings.HasPrefix(v, "go") {
|
||||||
|
return PlatformsLatest
|
||||||
|
}
|
||||||
|
// go-version only cares about version numbers
|
||||||
|
v = v[2:]
|
||||||
|
|
||||||
|
current, err := version.NewVersion(v)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Unable to parse current go version: %s\n%s", v, err.Error())
|
||||||
|
|
||||||
|
// Default to latest
|
||||||
|
return PlatformsLatest
|
||||||
|
}
|
||||||
|
|
||||||
|
var platforms = []struct {
|
||||||
|
constraint string
|
||||||
|
plat []Platform
|
||||||
|
}{
|
||||||
|
{"<= 1.0", Platforms_1_0},
|
||||||
|
{">= 1.1, < 1.3", Platforms_1_1},
|
||||||
|
{">= 1.3, < 1.4", Platforms_1_3},
|
||||||
|
{">= 1.4, < 1.5", Platforms_1_4},
|
||||||
|
{">= 1.5, < 1.6", Platforms_1_5},
|
||||||
|
{">= 1.6, < 1.7", Platforms_1_6},
|
||||||
|
{">= 1.7, < 1.8", Platforms_1_7},
|
||||||
|
{">= 1.8, < 1.9", Platforms_1_8},
|
||||||
|
{">= 1.9, < 1.10", Platforms_1_9},
|
||||||
|
{">=1.10, < 1.11", Platforms_1_10},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, p := range platforms {
|
||||||
|
constraints, err := version.NewConstraint(p.constraint)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if constraints.Check(current) {
|
||||||
|
return p.plat
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume latest
|
||||||
|
return Platforms_1_9
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PlatformFlag is a flag.Value (and flag.Getter) implementation that
|
||||||
|
// is used to track the os/arch flags on the command-line.
|
||||||
|
type PlatformFlag struct {
|
||||||
|
OS []string
|
||||||
|
Arch []string
|
||||||
|
OSArch []Platform
|
||||||
|
}
|
||||||
|
|
||||||
|
// Platforms returns the list of platforms that were set by this flag.
|
||||||
|
// The default set of platforms must be passed in.
|
||||||
|
func (p *PlatformFlag) Platforms(supported []Platform) []Platform {
|
||||||
|
// NOTE: Reading this method alone is a bit hard to understand. It
|
||||||
|
// is much easier to understand this method if you pair this with the
|
||||||
|
// table of test cases it has.
|
||||||
|
|
||||||
|
// Build a list of OS and archs NOT to build
|
||||||
|
ignoreArch := make(map[string]struct{})
|
||||||
|
includeArch := make(map[string]struct{})
|
||||||
|
ignoreOS := make(map[string]struct{})
|
||||||
|
includeOS := make(map[string]struct{})
|
||||||
|
ignoreOSArch := make(map[string]Platform)
|
||||||
|
includeOSArch := make(map[string]Platform)
|
||||||
|
for _, v := range p.Arch {
|
||||||
|
if v[0] == '!' {
|
||||||
|
ignoreArch[v[1:]] = struct{}{}
|
||||||
|
} else {
|
||||||
|
includeArch[v] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range p.OS {
|
||||||
|
if v[0] == '!' {
|
||||||
|
ignoreOS[v[1:]] = struct{}{}
|
||||||
|
} else {
|
||||||
|
includeOS[v] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range p.OSArch {
|
||||||
|
if v.OS[0] == '!' {
|
||||||
|
v = Platform{
|
||||||
|
OS: v.OS[1:],
|
||||||
|
Arch: v.Arch,
|
||||||
|
}
|
||||||
|
|
||||||
|
ignoreOSArch[v.String()] = v
|
||||||
|
} else {
|
||||||
|
includeOSArch[v.String()] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're building a list of new platforms, so build the list
|
||||||
|
// based only on the configured OS/arch pairs.
|
||||||
|
var prefilter []Platform = nil
|
||||||
|
if len(includeOSArch) > 0 {
|
||||||
|
prefilter = make([]Platform, 0, len(p.Arch)*len(p.OS)+len(includeOSArch))
|
||||||
|
for _, v := range includeOSArch {
|
||||||
|
prefilter = append(prefilter, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(includeOS) > 0 && len(includeArch) > 0 {
|
||||||
|
// Build up the list of prefiltered by what is specified
|
||||||
|
if prefilter == nil {
|
||||||
|
prefilter = make([]Platform, 0, len(p.Arch)*len(p.OS))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, os := range p.OS {
|
||||||
|
if _, ok := includeOS[os]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, arch := range p.Arch {
|
||||||
|
if _, ok := includeArch[arch]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
prefilter = append(prefilter, Platform{
|
||||||
|
OS: os,
|
||||||
|
Arch: arch,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if len(includeOS) > 0 {
|
||||||
|
// Build up the list of prefiltered by what is specified
|
||||||
|
if prefilter == nil {
|
||||||
|
prefilter = make([]Platform, 0, len(p.Arch)*len(p.OS))
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, os := range p.OS {
|
||||||
|
for _, platform := range supported {
|
||||||
|
if platform.OS == os {
|
||||||
|
prefilter = append(prefilter, platform)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if prefilter != nil {
|
||||||
|
// Remove any that aren't supported
|
||||||
|
result := make([]Platform, 0, len(prefilter))
|
||||||
|
for _, pending := range prefilter {
|
||||||
|
found := false
|
||||||
|
for _, platform := range supported {
|
||||||
|
if pending.String() == platform.String() {
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found {
|
||||||
|
add := pending
|
||||||
|
add.Default = false
|
||||||
|
result = append(result, add)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prefilter = result
|
||||||
|
}
|
||||||
|
|
||||||
|
if prefilter == nil {
|
||||||
|
prefilter = make([]Platform, 0, len(supported))
|
||||||
|
for _, v := range supported {
|
||||||
|
if v.Default {
|
||||||
|
add := v
|
||||||
|
add.Default = false
|
||||||
|
prefilter = append(prefilter, add)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Go through each default platform and filter out the bad ones
|
||||||
|
result := make([]Platform, 0, len(prefilter))
|
||||||
|
for _, platform := range prefilter {
|
||||||
|
if len(ignoreOSArch) > 0 {
|
||||||
|
if _, ok := ignoreOSArch[platform.String()]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only want to check the components (OS and Arch) if we didn't
|
||||||
|
// specifically ask to include it via the osarch.
|
||||||
|
checkComponents := true
|
||||||
|
if len(includeOSArch) > 0 {
|
||||||
|
if _, ok := includeOSArch[platform.String()]; ok {
|
||||||
|
checkComponents = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if checkComponents {
|
||||||
|
if len(ignoreArch) > 0 {
|
||||||
|
if _, ok := ignoreArch[platform.Arch]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(ignoreOS) > 0 {
|
||||||
|
if _, ok := ignoreOS[platform.OS]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(includeArch) > 0 {
|
||||||
|
if _, ok := includeArch[platform.Arch]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(includeOS) > 0 {
|
||||||
|
if _, ok := includeOS[platform.OS]; !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// ArchFlagValue returns a flag.Value that can be used with the flag
|
||||||
|
// package to collect the arches for the flag.
|
||||||
|
func (p *PlatformFlag) ArchFlagValue() flag.Value {
|
||||||
|
return (*appendStringValue)(&p.Arch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSFlagValue returns a flag.Value that can be used with the flag
|
||||||
|
// package to collect the operating systems for the flag.
|
||||||
|
func (p *PlatformFlag) OSFlagValue() flag.Value {
|
||||||
|
return (*appendStringValue)(&p.OS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSArchFlagValue returns a flag.Value that can be used with the flag
|
||||||
|
// package to collect complete os and arch pairs for the flag.
|
||||||
|
func (p *PlatformFlag) OSArchFlagValue() flag.Value {
|
||||||
|
return (*appendPlatformValue)(&p.OSArch)
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendPlatformValue is a flag.Value that appends a full platform (os/arch)
|
||||||
|
// to a list where the values from space-separated lines. This is used to
|
||||||
|
// satisfy the -osarch flag.
|
||||||
|
type appendPlatformValue []Platform
|
||||||
|
|
||||||
|
func (s *appendPlatformValue) String() string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *appendPlatformValue) Set(value string) error {
|
||||||
|
if value == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range strings.Split(value, " ") {
|
||||||
|
parts := strings.Split(v, "/")
|
||||||
|
if len(parts) != 2 {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"Invalid platform syntax: %s should be os/arch", v)
|
||||||
|
}
|
||||||
|
|
||||||
|
platform := Platform{
|
||||||
|
OS: strings.ToLower(parts[0]),
|
||||||
|
Arch: strings.ToLower(parts[1]),
|
||||||
|
}
|
||||||
|
|
||||||
|
s.appendIfMissing(&platform)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *appendPlatformValue) appendIfMissing(value *Platform) {
|
||||||
|
for _, existing := range *s {
|
||||||
|
if existing == *value {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*s = append(*s, *value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// appendStringValue is a flag.Value that appends values to the list,
|
||||||
|
// where the values come from space-separated lines. This is used to
|
||||||
|
// satisfy the -os="windows linux" flag to become []string{"windows", "linux"}
|
||||||
|
type appendStringValue []string
|
||||||
|
|
||||||
|
func (s *appendStringValue) String() string {
|
||||||
|
return strings.Join(*s, " ")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *appendStringValue) Set(value string) error {
|
||||||
|
for _, v := range strings.Split(value, " ") {
|
||||||
|
if v != "" {
|
||||||
|
s.appendIfMissing(strings.ToLower(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *appendStringValue) appendIfMissing(value string) {
|
||||||
|
for _, existing := range *s {
|
||||||
|
if existing == value {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*s = append(*s, value)
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/mitchellh/iochan"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The "main" method for when the toolchain build is requested.
|
||||||
|
func mainBuildToolchain(parallel int, platformFlag PlatformFlag, verbose bool) int {
|
||||||
|
if _, err := exec.LookPath("go"); err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "You must have Go already built for your native platform\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "and the `go` binary on the PATH to build toolchains.\n")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're version 1.5 or greater, then we don't need to do this anymore!
|
||||||
|
versionParts, err := GoVersionParts()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error reading Go version: %s", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if versionParts[0] >= 1 && versionParts[1] >= 5 {
|
||||||
|
fmt.Fprintf(
|
||||||
|
os.Stderr,
|
||||||
|
"-build-toolchain is no longer required for Go 1.5 or later.\n"+
|
||||||
|
"You can start using Gox immediately!\n")
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
version, err := GoVersion()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error reading Go version: %s", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
root, err := GoRoot()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "error finding GOROOT: %s\n", err)
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
fmt.Println("Verbose mode enabled. Output from building each toolchain will be")
|
||||||
|
fmt.Println("outputted to stdout as they are built.\n ")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine the platforms we're building the toolchain for.
|
||||||
|
platforms := platformFlag.Platforms(SupportedPlatforms(version))
|
||||||
|
|
||||||
|
// The toolchain build can't be parallelized.
|
||||||
|
if parallel > 1 {
|
||||||
|
fmt.Println("The toolchain build can't be parallelized because compiling a single")
|
||||||
|
fmt.Println("Go source directory can only be done for one platform at a time. Therefore,")
|
||||||
|
fmt.Println("the toolchain for each platform will be built one at a time.\n ")
|
||||||
|
}
|
||||||
|
parallel = 1
|
||||||
|
|
||||||
|
var errorLock sync.Mutex
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
errs := make([]error, 0)
|
||||||
|
semaphore := make(chan int, parallel)
|
||||||
|
for _, platform := range platforms {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(platform Platform) {
|
||||||
|
err := buildToolchain(&wg, semaphore, root, platform, verbose)
|
||||||
|
if err != nil {
|
||||||
|
errorLock.Lock()
|
||||||
|
defer errorLock.Unlock()
|
||||||
|
errs = append(errs, fmt.Errorf("%s: %s", platform.String(), err))
|
||||||
|
}
|
||||||
|
}(platform)
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
fmt.Fprintf(os.Stderr, "\n%d errors occurred:\n", len(errs))
|
||||||
|
for _, err := range errs {
|
||||||
|
fmt.Fprintf(os.Stderr, "%s\n", err)
|
||||||
|
}
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildToolchain(wg *sync.WaitGroup, semaphore chan int, root string, platform Platform, verbose bool) error {
|
||||||
|
defer wg.Done()
|
||||||
|
semaphore <- 1
|
||||||
|
defer func() { <-semaphore }()
|
||||||
|
fmt.Printf("--> Toolchain: %s\n", platform.String())
|
||||||
|
|
||||||
|
scriptName := "make.bash"
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
scriptName = "make.bat"
|
||||||
|
}
|
||||||
|
|
||||||
|
var stderr bytes.Buffer
|
||||||
|
var stdout bytes.Buffer
|
||||||
|
scriptDir := filepath.Join(root, "src")
|
||||||
|
scriptPath := filepath.Join(scriptDir, scriptName)
|
||||||
|
cmd := exec.Command(scriptPath, "--no-clean")
|
||||||
|
cmd.Dir = scriptDir
|
||||||
|
cmd.Env = append(os.Environ(),
|
||||||
|
"GOARCH="+platform.Arch,
|
||||||
|
"GOOS="+platform.OS)
|
||||||
|
cmd.Stderr = &stderr
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
|
||||||
|
if verbose {
|
||||||
|
// In verbose mode, we output all stdout to the console.
|
||||||
|
r, w := io.Pipe()
|
||||||
|
cmd.Stdout = w
|
||||||
|
cmd.Stderr = io.MultiWriter(cmd.Stderr, w)
|
||||||
|
|
||||||
|
// Send all the output to stdout, and also make a done channel
|
||||||
|
// so that this compilation isn't done until we receive all output
|
||||||
|
doneCh := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(doneCh)
|
||||||
|
for line := range iochan.DelimReader(r, '\n') {
|
||||||
|
fmt.Printf("%s: %s", platform.String(), line)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
defer func() {
|
||||||
|
w.Close()
|
||||||
|
<-doneCh
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmd.Start(); err != nil {
|
||||||
|
return fmt.Errorf("Error building '%s': %s", platform.String(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
return fmt.Errorf("Error building '%s'.\n\nStdout: %s\n\nStderr: %s\n",
|
||||||
|
platform.String(), stdout.String(), stderr.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Mitchell Hashimoto
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
|
@ -0,0 +1,13 @@
|
||||||
|
# iochan
|
||||||
|
|
||||||
|
iochan is a Go library for treating `io` readers and writers like channels.
|
||||||
|
This is useful when sometimes you wish to use `io.Reader` and such in `select`
|
||||||
|
statements.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Standard `go get`:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ go get github.com/mitchellh/iochan
|
||||||
|
```
|
|
@ -0,0 +1 @@
|
||||||
|
module github.com/mitchellh/iochan
|
|
@ -0,0 +1,41 @@
|
||||||
|
package iochan
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DelimReader takes an io.Reader and produces the contents of the reader
|
||||||
|
// on the returned channel. The contents on the channel will be returned
|
||||||
|
// on boundaries specified by the delim parameter, and will include this
|
||||||
|
// delimiter.
|
||||||
|
//
|
||||||
|
// If an error occurs while reading from the reader, the reading will end.
|
||||||
|
//
|
||||||
|
// In the case of an EOF or error, the channel will be closed.
|
||||||
|
//
|
||||||
|
// This must only be called once for any individual reader. The behavior is
|
||||||
|
// unknown and will be unexpected if this is called multiple times with the
|
||||||
|
// same reader.
|
||||||
|
func DelimReader(r io.Reader, delim byte) <-chan string {
|
||||||
|
ch := make(chan string)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
buf := bufio.NewReader(r)
|
||||||
|
|
||||||
|
for {
|
||||||
|
line, err := buf.ReadString(delim)
|
||||||
|
if line != "" {
|
||||||
|
ch <- line
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(ch)
|
||||||
|
}()
|
||||||
|
|
||||||
|
return ch
|
||||||
|
}
|
|
@ -496,9 +496,14 @@ github.com/mitchellh/go-testing-interface
|
||||||
# github.com/mitchellh/go-wordwrap v1.0.0
|
# github.com/mitchellh/go-wordwrap v1.0.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mitchellh/go-wordwrap
|
github.com/mitchellh/go-wordwrap
|
||||||
|
# github.com/mitchellh/gox v1.0.1
|
||||||
|
## explicit
|
||||||
|
github.com/mitchellh/gox
|
||||||
# github.com/mitchellh/hashstructure v1.0.0
|
# github.com/mitchellh/hashstructure v1.0.0
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mitchellh/hashstructure
|
github.com/mitchellh/hashstructure
|
||||||
|
# github.com/mitchellh/iochan v1.0.0
|
||||||
|
github.com/mitchellh/iochan
|
||||||
# github.com/mitchellh/mapstructure v1.1.2
|
# github.com/mitchellh/mapstructure v1.1.2
|
||||||
## explicit
|
## explicit
|
||||||
github.com/mitchellh/mapstructure
|
github.com/mitchellh/mapstructure
|
||||||
|
|
Loading…
Reference in New Issue