Merge pull request #25272 from hashicorp/ci/add-gox-tools
Add `gox` to tools package
This commit is contained in:
commit
1a43187e49
|
@ -165,6 +165,16 @@ jobs:
|
|||
XC_OS: "freebsd linux"
|
||||
XC_ARCH: "arm"
|
||||
|
||||
test-docker-full:
|
||||
executor:
|
||||
name: go
|
||||
steps:
|
||||
- checkout
|
||||
- setup_remote_docker
|
||||
- run:
|
||||
name: test docker build for 'full' image
|
||||
command: docker build -t test-docker-full .
|
||||
|
||||
workflows:
|
||||
version: 2
|
||||
test:
|
||||
|
@ -180,6 +190,13 @@ workflows:
|
|||
requires:
|
||||
- go-test
|
||||
- go-test-e2e
|
||||
- test-docker-full:
|
||||
filters:
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- /^v\d+\.\d+$/ # v0.11, v0.12, etc.
|
||||
|
||||
build-distros:
|
||||
jobs:
|
||||
- build-386
|
||||
|
|
1
go.mod
1
go.mod
|
@ -94,6 +94,7 @@ require (
|
|||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/mitchellh/go-linereader v0.0.0-20190213213312-1b945b3263eb
|
||||
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/mapstructure v1.1.2
|
||||
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-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-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/go.mod h1:YF5j7IQtrOAOnsGkniupEA5bfCjzd7i14yu0shZavyM=
|
||||
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.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
||||
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.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
|
||||
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 v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||
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/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/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
|
||||
|
|
|
@ -6,7 +6,7 @@ gofmt_files=$(gofmt -l `find . -name '*.go' | grep -v vendor`)
|
|||
if [[ -n ${gofmt_files} ]]; then
|
||||
echo 'gofmt needs running on the following files:'
|
||||
echo "${gofmt_files}"
|
||||
echo "You can use the command: \`make fmt\` to reformat code."
|
||||
echo "You can use the command: \`make fmtcheck\` to reformat code."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ package tools
|
|||
|
||||
import (
|
||||
_ "github.com/golang/mock/mockgen"
|
||||
_ "github.com/mitchellh/gox"
|
||||
_ "golang.org/x/tools/cmd/cover"
|
||||
_ "golang.org/x/tools/cmd/stringer"
|
||||
)
|
||||
|
|
|
@ -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
|
||||
## explicit
|
||||
github.com/mitchellh/go-wordwrap
|
||||
# github.com/mitchellh/gox v1.0.1
|
||||
## explicit
|
||||
github.com/mitchellh/gox
|
||||
# github.com/mitchellh/hashstructure v1.0.0
|
||||
## explicit
|
||||
github.com/mitchellh/hashstructure
|
||||
# github.com/mitchellh/iochan v1.0.0
|
||||
github.com/mitchellh/iochan
|
||||
# github.com/mitchellh/mapstructure v1.1.2
|
||||
## explicit
|
||||
github.com/mitchellh/mapstructure
|
||||
|
|
Loading…
Reference in New Issue