@ -120,8 +120,6 @@ func main() {
doArchive ( os . Args [ 2 : ] )
doArchive ( os . Args [ 2 : ] )
case "debsrc" :
case "debsrc" :
doDebianSource ( os . Args [ 2 : ] )
doDebianSource ( os . Args [ 2 : ] )
case "travis-debsrc" :
doTravisDebianSource ( os . Args [ 2 : ] )
case "xgo" :
case "xgo" :
doXgo ( os . Args [ 2 : ] )
doXgo ( os . Args [ 2 : ] )
default :
default :
@ -132,8 +130,8 @@ func main() {
// Compiling
// Compiling
func doInstall ( cmdline [ ] string ) {
func doInstall ( cmdline [ ] string ) {
commitHash := flag . String ( "gitcommit" , "" , "Git commit hash embedded into binary." )
flag . CommandLine . Parse ( cmdline )
flag . CommandLine . Parse ( cmdline )
env := build . Env ( )
// Check Go version. People regularly open issues about compilation
// Check Go version. People regularly open issues about compilation
// failure with outdated Go. This should save them the trouble.
// failure with outdated Go. This should save them the trouble.
@ -150,13 +148,17 @@ func doInstall(cmdline []string) {
packages = flag . Args ( )
packages = flag . Args ( )
}
}
goinstall := goTool ( "install" , makeBuildFlags ( * commitHash ) ... )
goinstall := goTool ( "install" , buildFlags ( env ) ... )
goinstall . Args = append ( goinstall . Args , "-v" )
goinstall . Args = append ( goinstall . Args , "-v" )
goinstall . Args = append ( goinstall . Args , packages ... )
goinstall . Args = append ( goinstall . Args , packages ... )
build . MustRun ( goinstall )
build . MustRun ( goinstall )
}
}
func makeBuildFlags ( commitHash string ) ( flags [ ] string ) {
func buildFlags ( env build . Environment ) ( flags [ ] string ) {
if os . Getenv ( "GO_OPENCL" ) != "" {
flags = append ( flags , "-tags" , "opencl" )
}
// Since Go 1.5, the separator char for link time assignments
// Since Go 1.5, the separator char for link time assignments
// is '=' and using ' ' prints a warning. However, Go < 1.5 does
// is '=' and using ' ' prints a warning. However, Go < 1.5 does
// not support using '='.
// not support using '='.
@ -164,26 +166,9 @@ func makeBuildFlags(commitHash string) (flags []string) {
if runtime . Version ( ) > "go1.5" || strings . Contains ( runtime . Version ( ) , "devel" ) {
if runtime . Version ( ) > "go1.5" || strings . Contains ( runtime . Version ( ) , "devel" ) {
sep = "="
sep = "="
}
}
// Set gitCommit constant via link-time assignment.
if os . Getenv ( "GO_OPENCL" ) != "" {
if env . Commit != "" {
flags = append ( flags , "-tags" , "opencl" )
flags = append ( flags , "-ldflags" , "-X main.gitCommit" + sep + env . Commit )
}
// Set gitCommit constant via link-time assignment. If this is a git checkout, we can
// just get the current commit hash through git. Otherwise we fall back to the hash
// that was passed as -gitcommit.
//
// -gitcommit is required for Debian package builds. The source package doesn't
// contain .git but we still want to embed the commit hash into the packaged binary.
// The hash is rendered into the debian/rules build script when the source package is
// created.
if _ , err := os . Stat ( filepath . Join ( ".git" , "HEAD" ) ) ; ! os . IsNotExist ( err ) {
if c := build . GitCommit ( ) ; c != "" {
commitHash = c
}
}
if commitHash != "" {
flags = append ( flags , "-ldflags" , "-X main.gitCommit" + sep + commitHash )
}
}
return flags
return flags
}
}
@ -253,7 +238,11 @@ func doArchive(cmdline []string) {
default :
default :
log . Fatal ( "unknown archive type: " , atype )
log . Fatal ( "unknown archive type: " , atype )
}
}
base := makeArchiveBasename ( )
env := build . Env ( )
maybeSkipArchive ( env )
base := archiveBasename ( env )
if err := build . WriteArchive ( "geth-" + base , ext , gethArchiveFiles ) ; err != nil {
if err := build . WriteArchive ( "geth-" + base , ext , gethArchiveFiles ) ; err != nil {
log . Fatal ( err )
log . Fatal ( err )
}
}
@ -262,88 +251,63 @@ func doArchive(cmdline []string) {
}
}
}
}
func m akeA rchiveBasename( ) string {
func archiveBasename ( env build . Environment ) string {
// date := time.Now().UTC().Format("200601021504")
// date := time.Now().UTC().Format("200601021504")
platform := runtime . GOOS + "-" + runtime . GOARCH
platform := runtime . GOOS + "-" + runtime . GOARCH
archive := platform + "-" + build . VERSION ( )
archive := platform + "-" + build . VERSION ( )
if commit := build . GitCommit ( ) ; c ommit != "" {
if env . C ommit != "" {
archive += "-" + c ommit[ : 8 ]
archive += "-" + env . C ommit[ : 8 ]
}
}
return archive
return archive
}
}
// Debian Packaging
// skips archiving for some build configurations.
func maybeSkipArchive ( env build . Environment ) {
// CLI entry point for Travis CI.
if env . IsPullRequest {
func doTravisDebianSource ( cmdline [ ] string ) {
flag . CommandLine . Parse ( cmdline )
// Package only whitelisted branches.
switch {
case os . Getenv ( "TRAVIS_REPO_SLUG" ) != "ethereum/go-ethereum" :
log . Printf ( "skipping because this is a fork build" )
return
case os . Getenv ( "TRAVIS_PULL_REQUEST" ) != "false" :
log . Printf ( "skipping because this is a PR build" )
log . Printf ( "skipping because this is a PR build" )
return
os . Exit ( 0 )
case os . Getenv ( "TRAVIS_BRANCH" ) != "develop" && ! strings . HasPrefix ( os . Getenv ( "TRAVIS_TAG" ) , "v1." ) :
log . Printf ( "skipping because branch %q tag %q is not on the whitelist" ,
os . Getenv ( "TRAVIS_BRANCH" ) ,
os . Getenv ( "TRAVIS_TAG" ) )
return
}
// Import the signing key.
if b64key := os . Getenv ( "PPA_SIGNING_KEY" ) ; b64key != "" {
key , err := base64 . StdEncoding . DecodeString ( b64key )
if err != nil {
log . Fatal ( "invalid base64 PPA_SIGNING_KEY" )
}
}
gpg := exec . Command ( "gpg" , "--import" )
if env . Branch != "develop" && ! strings . HasPrefix ( env . Tag , "v1." ) {
gpg . Stdin = bytes . NewReader ( key )
log . Printf ( "skipping because branch %q, tag %q is not on the whitelist" , env . Branch , env . Tag )
build . MustRun ( gpg )
os . Exit ( 0 )
}
}
// Assign unstable status to non-tag builds.
unstable := "true"
if os . Getenv ( "TRAVIS_BRANCH" ) != "develop" && os . Getenv ( "TRAVIS_TAG" ) != "" {
unstable = "false"
}
}
doDebianSource ( [ ] string {
// Debian Packaging
"-signer" , "Felix Lange (Geth CI Testing Key) <fjl@twurst.com>" ,
"-buildnum" , os . Getenv ( "TRAVIS_BUILD_NUMBER" ) ,
"-upload" , "ppa:lp-fjl/geth-ci-testing" ,
"-unstable" , unstable ,
} )
}
// CLI entry point for doing packaging locally.
func doDebianSource ( cmdline [ ] string ) {
func doDebianSource ( cmdline [ ] string ) {
var (
var (
signer = flag . String ( "signer" , "" , ` Signing key name, also used as package author ` )
signer = flag . String ( "signer" , "" , ` Signing key name, also used as package author ` )
upload = flag . String ( "upload" , "" , ` Where to upload the source package (usually "ppa:ethereum/ethereum") ` )
upload = flag . String ( "upload" , "" , ` Where to upload the source package (usually "ppa:ethereum/ethereum") ` )
buildnum = flag . String ( "buildnum" , "" , ` Build number (included in version) ` )
workdir = flag . String ( "workdir" , "" , ` Output directory for packages (uses temp dir if unset) ` )
unstable = flag . Bool ( "unstable" , false , ` Use package name suffix "-unstable" ` )
now = time . Now ( )
now = time . Now ( )
)
)
flag . CommandLine . Parse ( cmdline )
flag . CommandLine . Parse ( cmdline )
* workdir = makeWorkdir ( * workdir )
env := build . Env ( )
maybeSkipArchive ( env )
// Create the debian worktree in /tmp.
// Import the signing key.
tmpdir , err := ioutil . TempDir ( "" , "eth-deb-build-" )
if b64key := os . Getenv ( "PPA_SIGNING_KEY" ) ; b64key != "" {
key , err := base64 . StdEncoding . DecodeString ( b64key )
if err != nil {
if err != nil {
log . Fatal ( err )
log . Fatal ( "invalid base64 PPA_SIGNING_KEY" )
}
gpg := exec . Command ( "gpg" , "--import" )
gpg . Stdin = bytes . NewReader ( key )
build . MustRun ( gpg )
}
}
// Create the packages.
for _ , distro := range debDistros {
for _ , distro := range debDistros {
meta := newDebMetadata ( distro , * signer , * buildnum , * unstable , now )
meta := newDebMetadata ( distro , * signer , env , now )
pkgdir := stageDebianSource ( tmp dir, meta )
pkgdir := stageDebianSource ( * work dir, meta )
debuild := exec . Command ( "debuild" , "-S" , "-sa" , "-us" , "-uc" )
debuild := exec . Command ( "debuild" , "-S" , "-sa" , "-us" , "-uc" )
debuild . Dir = pkgdir
debuild . Dir = pkgdir
build . MustRun ( debuild )
build . MustRun ( debuild )
changes := fmt . Sprintf ( "%s_%s_source.changes" , meta . Name ( ) , meta . VersionString ( ) )
changes := fmt . Sprintf ( "%s_%s_source.changes" , meta . Name ( ) , meta . VersionString ( ) )
changes = filepath . Join ( tmp dir, changes )
changes = filepath . Join ( * work dir, changes )
if * signer != "" {
if * signer != "" {
build . MustRunCommand ( "debsign" , changes )
build . MustRunCommand ( "debsign" , changes )
}
}
@ -353,35 +317,53 @@ func doDebianSource(cmdline []string) {
}
}
}
}
type debExecutable struct {
func makeWorkdir ( wdflag string ) string {
Name , Description string
var err error
if wdflag != "" {
err = os . MkdirAll ( wdflag , 0744 )
} else {
wdflag , err = ioutil . TempDir ( "" , "eth-deb-build-" )
}
if err != nil {
log . Fatal ( err )
}
return wdflag
}
func isUnstableBuild ( env build . Environment ) bool {
if env . Branch != "develop" && env . Tag != "" {
return false
}
return true
}
}
type debMetadata struct {
type debMetadata struct {
Env build . Environment
// go-ethereum version being built. Note that this
// go-ethereum version being built. Note that this
// is not the debian package version. The package version
// is not the debian package version. The package version
// is constructed by VersionString.
// is constructed by VersionString.
Version string
Version string
Author string // "name <email>", also selects signing key
Author string // "name <email>", also selects signing key
Buildnum string // build number
Distro , Time string
Distro , Commit , Time string
Executables [ ] debExecutable
Executables [ ] debExecutable
Unstable bool
}
}
func newDebMetadata ( distro , author , buildnum string , unstable bool , t time . Time ) debMetadata {
type debExecutable struct {
Name , Description string
}
func newDebMetadata ( distro , author string , env build . Environment , t time . Time ) debMetadata {
if author == "" {
if author == "" {
// No signing key, use default author.
// No signing key, use default author.
author = "Ethereum Builds <fjl@ethereum.org>"
author = "Ethereum Builds <fjl@ethereum.org>"
}
}
return debMetadata {
return debMetadata {
Unstable : unstable ,
Env : env ,
Author : author ,
Author : author ,
Distro : distro ,
Distro : distro ,
Commit : build . GitCommit ( ) ,
Version : build . VERSION ( ) ,
Version : build . VERSION ( ) ,
Buildnum : buildnum ,
Time : t . Format ( time . RFC1123Z ) ,
Time : t . Format ( time . RFC1123Z ) ,
Executables : debExecutables ,
Executables : debExecutables ,
}
}
@ -390,7 +372,7 @@ func newDebMetadata(distro, author, buildnum string, unstable bool, t time.Time)
// Name returns the name of the metapackage that depends
// Name returns the name of the metapackage that depends
// on all executable packages.
// on all executable packages.
func ( meta debMetadata ) Name ( ) string {
func ( meta debMetadata ) Name ( ) string {
if meta . Unstable {
if isUnstableBuild ( meta . Env ) {
return "ethereum-unstable"
return "ethereum-unstable"
}
}
return "ethereum"
return "ethereum"
@ -399,8 +381,8 @@ func (meta debMetadata) Name() string {
// VersionString returns the debian version of the packages.
// VersionString returns the debian version of the packages.
func ( meta debMetadata ) VersionString ( ) string {
func ( meta debMetadata ) VersionString ( ) string {
vsn := meta . Version
vsn := meta . Version
if meta . Buildnum != "" {
if meta . Env . Buildnum != "" {
vsn += "+build" + meta . Buildnum
vsn += "+build" + meta . Env . Buildnum
}
}
if meta . Distro != "" {
if meta . Distro != "" {
vsn += "+" + meta . Distro
vsn += "+" + meta . Distro
@ -419,7 +401,7 @@ func (meta debMetadata) ExeList() string {
// ExeName returns the package name of an executable package.
// ExeName returns the package name of an executable package.
func ( meta debMetadata ) ExeName ( exe debExecutable ) string {
func ( meta debMetadata ) ExeName ( exe debExecutable ) string {
if meta . Unstable {
if isUnstableBuild ( meta . Env ) {
return exe . Name + "-unstable"
return exe . Name + "-unstable"
}
}
return exe . Name
return exe . Name
@ -428,7 +410,7 @@ func (meta debMetadata) ExeName(exe debExecutable) string {
// ExeConflicts returns the content of the Conflicts field
// ExeConflicts returns the content of the Conflicts field
// for executable packages.
// for executable packages.
func ( meta debMetadata ) ExeConflicts ( exe debExecutable ) string {
func ( meta debMetadata ) ExeConflicts ( exe debExecutable ) string {
if meta . Unstable {
if isUnstableBuild ( meta . Env ) {
// Set up the conflicts list so that the *-unstable packages
// Set up the conflicts list so that the *-unstable packages
// cannot be installed alongside the regular version.
// cannot be installed alongside the regular version.
//
//
@ -461,8 +443,8 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) {
build . RenderString ( "8\n" , filepath . Join ( debian , "compat" ) , 0644 , meta )
build . RenderString ( "8\n" , filepath . Join ( debian , "compat" ) , 0644 , meta )
build . RenderString ( "3.0 (native)\n" , filepath . Join ( debian , "source/format" ) , 0644 , meta )
build . RenderString ( "3.0 (native)\n" , filepath . Join ( debian , "source/format" ) , 0644 , meta )
for _ , exe := range meta . Executables {
for _ , exe := range meta . Executables {
install := filepath . Join ( debian , exe . Name + ".install" )
install := filepath . Join ( debian , meta . ExeName ( exe ) + ".install" )
docs := filepath . Join ( debian , exe . Name + ".docs" )
docs := filepath . Join ( debian , meta . ExeName ( exe ) + ".docs" )
build . Render ( "build/deb.install" , install , 0644 , exe )
build . Render ( "build/deb.install" , install , 0644 , exe )
build . Render ( "build/deb.docs" , docs , 0644 , exe )
build . Render ( "build/deb.docs" , docs , 0644 , exe )
}
}
@ -473,18 +455,19 @@ func stageDebianSource(tmpdir string, meta debMetadata) (pkgdir string) {
// Cross compilation
// Cross compilation
func doXgo ( cmdline [ ] string ) {
func doXgo ( cmdline [ ] string ) {
flag . CommandLine . Parse ( cmdline )
env := build . Env ( )
// Make sure xgo is available for cross compilation
// Make sure xgo is available for cross compilation
gogetxgo := goTool ( "get" , "github.com/karalabe/xgo" )
gogetxgo := goTool ( "get" , "github.com/karalabe/xgo" )
build . MustRun ( gogetxgo )
build . MustRun ( gogetxgo )
// Execute the actual cross compilation
// Execute the actual cross compilation
pkg := cmdline [ len ( cmdline ) - 1 ]
xgo := xgoTool ( append ( buildFlags ( env ) , flag . Args ( ) ... ) )
args := append ( cmdline [ : len ( cmdline ) - 1 ] , makeBuildFlags ( "" ) ... )
build . MustRun ( xgo )
build . MustRun ( xgoTool ( append ( args , pkg ) ... ) )
}
}
func xgoTool ( args ... string ) * exec . Cmd {
func xgoTool ( args [ ] string ) * exec . Cmd {
cmd := exec . Command ( filepath . Join ( GOBIN , "xgo" ) , args ... )
cmd := exec . Command ( filepath . Join ( GOBIN , "xgo" ) , args ... )
cmd . Env = [ ] string {
cmd . Env = [ ] string {
"GOPATH=" + build . GOPATH ( ) ,
"GOPATH=" + build . GOPATH ( ) ,