build: iOS XCode framework build and upload

This commit is contained in:
Péter Szilágyi 2016-11-09 11:13:37 +02:00
parent b7dfd333c5
commit 322502b441
No known key found for this signature in database
GPG Key ID: 119A76381CCB7DD2
4 changed files with 140 additions and 25 deletions

View File

@ -63,7 +63,11 @@ matrix:
- go run build/ci.go install - go run build/ci.go install
- go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds
# Build the Android archives and upload them to Maven Central # Build the iOS framework and upload it to CocoaPods and Azure
- gem install cocoapods --pre
- go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload gethstore/builds
# Build the Android archive and upload it to Maven Central and Azure
- brew update - brew update
- brew install android-sdk maven - brew install android-sdk maven
- export ANDROID_HOME=/usr/local/opt/android-sdk - export ANDROID_HOME=/usr/local/opt/android-sdk

View File

@ -29,7 +29,8 @@ Available commands are:
importkeys -- imports signing keys from env importkeys -- imports signing keys from env
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
nsis -- creates a Windows NSIS installer nsis -- creates a Windows NSIS installer
aar [ -sign key-id ] [ -upload dest ] -- creates an android archive aar [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an Android archive
xcode [ -sign key-id ] [-deploy repo] [ -upload dest ] -- creates an iOS XCode framework
xgo [ options ] -- cross builds according to options xgo [ options ] -- cross builds according to options
For all commands, -n prevents execution of external programs (dry run mode). For all commands, -n prevents execution of external programs (dry run mode).
@ -130,6 +131,8 @@ func main() {
doWindowsInstaller(os.Args[2:]) doWindowsInstaller(os.Args[2:])
case "aar": case "aar":
doAndroidArchive(os.Args[2:]) doAndroidArchive(os.Args[2:])
case "xcode":
doXCodeFramework(os.Args[2:])
case "xgo": case "xgo":
doXgo(os.Args[2:]) doXgo(os.Args[2:])
default: default:
@ -339,14 +342,21 @@ func archiveBasename(arch string, env build.Environment) string {
if arch == "android" { if arch == "android" {
platform = "android-all" platform = "android-all"
} }
archive := platform + "-" + build.VERSION() if arch == "ios" {
platform = "ios-all"
}
return platform + "-" + archiveVersion(env)
}
func archiveVersion(env build.Environment) string {
version := build.VERSION()
if isUnstableBuild(env) { if isUnstableBuild(env) {
archive += "-unstable" version += "-unstable"
} }
if env.Commit != "" { if env.Commit != "" {
archive += "-" + env.Commit[:8] version += "-" + env.Commit[:8]
} }
return archive return version
} }
func archiveUpload(archive string, blobstore string, signer string) error { func archiveUpload(archive string, blobstore string, signer string) error {
@ -638,14 +648,15 @@ func doWindowsInstaller(cmdline []string) {
if err := archiveUpload(installer, *upload, *signer); err != nil { if err := archiveUpload(installer, *upload, *signer); err != nil {
log.Fatal(err) log.Fatal(err)
} }
}
// Android archives // Android archives
func doAndroidArchive(cmdline []string) { func doAndroidArchive(cmdline []string) {
var ( var (
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`) signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
deploy = flag.String("deploy", "", `Where to upload the deploy the archive (usually "https://oss.sonatype.org")`) deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`) upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
) )
flag.CommandLine.Parse(cmdline) flag.CommandLine.Parse(cmdline)
env := build.Env() env := build.Env()
@ -656,13 +667,13 @@ func doAndroidArchive(cmdline []string) {
build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile")) build.MustRun(gomobileTool("bind", "--target", "android", "--javapkg", "org.ethereum", "-v", "github.com/ethereum/go-ethereum/mobile"))
meta := newMavenMetadata(env) meta := newMavenMetadata(env)
build.Render("build/mvn.pom", meta.PackageString()+".pom", 0755, meta) build.Render("build/mvn.pom", meta.Package+".pom", 0755, meta)
// Skip Maven deploy and Azure upload for PR builds // Skip Maven deploy and Azure upload for PR builds
maybeSkipArchive(env) maybeSkipArchive(env)
// Sign and upload all the artifacts to Maven Central // Sign and upload all the artifacts to Maven Central
os.Rename("geth.aar", meta.PackageString()+".aar") os.Rename("geth.aar", meta.Package+".aar")
if *signer != "" && *deploy != "" { if *signer != "" && *deploy != "" {
// Import the signing key into the local GPG instance // Import the signing key into the local GPG instance
if b64key := os.Getenv(*signer); b64key != "" { if b64key := os.Getenv(*signer); b64key != "" {
@ -676,16 +687,16 @@ func doAndroidArchive(cmdline []string) {
} }
// Upload the artifacts to Sonatype and/or Maven Central // Upload the artifacts to Sonatype and/or Maven Central
repo := *deploy + "/service/local/staging/deploy/maven2" repo := *deploy + "/service/local/staging/deploy/maven2"
if meta.Unstable { if meta.Develop {
repo = *deploy + "/content/repositories/snapshots" repo = *deploy + "/content/repositories/snapshots"
} }
build.MustRunCommand("mvn", "gpg:sign-and-deploy-file", build.MustRunCommand("mvn", "gpg:sign-and-deploy-file",
"-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh", "-settings=build/mvn.settings", "-Durl="+repo, "-DrepositoryId=ossrh",
"-DpomFile="+meta.PackageString()+".pom", "-Dfile="+meta.PackageString()+".aar") "-DpomFile="+meta.Package+".pom", "-Dfile="+meta.Package+".aar")
} }
// Sign and upload the archive to Azure // Sign and upload the archive to Azure
archive := "geth-" + archiveBasename("android", env) + ".aar" archive := "geth-" + archiveBasename("android", env) + ".aar"
os.Rename(meta.PackageString()+".aar", archive) os.Rename(meta.Package+".aar", archive)
if err := archiveUpload(archive, *upload, *signer); err != nil { if err := archiveUpload(archive, *upload, *signer); err != nil {
log.Fatal(err) log.Fatal(err)
@ -708,9 +719,9 @@ func gomobileTool(subcmd string, args ...string) *exec.Cmd {
} }
type mavenMetadata struct { type mavenMetadata struct {
Env build.Environment
Version string Version string
Unstable bool Package string
Develop bool
Contributors []mavenContributor Contributors []mavenContributor
} }
@ -740,23 +751,101 @@ func newMavenMetadata(env build.Environment) mavenMetadata {
} }
} }
} }
// Render the version and package strings
version := build.VERSION()
if isUnstableBuild(env) {
version += "-SNAPSHOT"
}
return mavenMetadata{ return mavenMetadata{
Env: env, Version: version,
Version: build.VERSION(), Package: "geth-" + version,
Unstable: isUnstableBuild(env), Develop: isUnstableBuild(env),
Contributors: contribs, Contributors: contribs,
} }
} }
func (meta mavenMetadata) VersionString() string { // XCode frameworks
if meta.Unstable {
return meta.Version + "-SNAPSHOT" func doXCodeFramework(cmdline []string) {
var (
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
// Build the iOS XCode framework
build.MustRun(goTool("get", "golang.org/x/mobile/cmd/gomobile"))
build.MustRun(gomobileTool("init"))
archive := "geth-" + archiveBasename("ios", env)
if err := os.Mkdir(archive, os.ModePerm); err != nil {
log.Fatal(err)
}
bind := gomobileTool("bind", "--target", "ios", "--tags", "ios", "--prefix", "GE", "-v", "github.com/ethereum/go-ethereum/mobile")
bind.Dir, _ = filepath.Abs(archive)
build.MustRun(bind)
build.MustRunCommand("tar", "-zcvf", archive+".tar.gz", archive)
// Skip CocoaPods deploy and Azure upload for PR builds
maybeSkipArchive(env)
// Sign and upload the framework to Azure
if err := archiveUpload(archive+".tar.gz", *upload, *signer); err != nil {
log.Fatal(err)
}
// Prepare and upload a PodSpec to CocoaPods
if *deploy != "" {
meta := newPodMetadata(env)
build.Render("build/pod.podspec", meta.Name+".podspec", 0755, meta)
build.MustRunCommand("pod", *deploy, "push", meta.Name+".podspec")
} }
return meta.Version
} }
func (meta mavenMetadata) PackageString() string { type podMetadata struct {
return "geth-" + meta.VersionString() Name string
Version string
Commit string
Contributors []podContributor
}
type podContributor struct {
Name string
Email string
}
func newPodMetadata(env build.Environment) podMetadata {
// Collect the list of authors from the repo root
contribs := []podContributor{}
if authors, err := os.Open("AUTHORS"); err == nil {
defer authors.Close()
scanner := bufio.NewScanner(authors)
for scanner.Scan() {
// Skip any whitespace from the authors list
line := strings.TrimSpace(scanner.Text())
if line == "" || line[0] == '#' {
continue
}
// Split the author and insert as a contributor
re := regexp.MustCompile("([^<]+) <(.+>)")
parts := re.FindStringSubmatch(line)
if len(parts) == 3 {
contribs = append(contribs, podContributor{Name: parts[1], Email: parts[2]})
}
}
}
name := "Geth"
if isUnstableBuild(env) {
name += "Develop"
}
return podMetadata{
Name: name,
Version: archiveVersion(env),
Commit: env.Commit,
Contributors: contribs,
}
} }
// Cross compilation // Cross compilation

View File

@ -6,7 +6,7 @@
<groupId>org.ethereum</groupId> <groupId>org.ethereum</groupId>
<artifactId>geth</artifactId> <artifactId>geth</artifactId>
<version>{{.VersionString}}</version> <version>{{.Version}}</version>
<packaging>aar</packaging> <packaging>aar</packaging>
<name>Android Ethereum Client</name> <name>Android Ethereum Client</name>

22
build/pod.podspec Normal file
View File

@ -0,0 +1,22 @@
Pod::Spec.new do |spec|
spec.name = '{{.Name}}'
spec.version = '{{.Version}}'
spec.license = { :type => 'GNU Lesser General Public License, Version 3.0' }
spec.homepage = 'https://github.com/ethereum/go-ethereum'
spec.authors = { {{range .Contributors}}
'{{.Name}}' => '{{.Email}}',{{end}}
}
spec.summary = 'iOS Ethereum Client'
spec.source = { :git => 'https://github.com/ethereum/go-ethereum.git', :commit => '{{.Commit}}' }
spec.platform = :ios
spec.ios.deployment_target = '9.0'
spec.ios.vendored_frameworks = 'Frameworks/Geth.framework'
spec.prepare_command = <<-CMD
curl https://gethstore.blob.core.windows.net/builds/geth-ios-all-{{.Version}}.tar.gz | tar -xvz
mkdir Frameworks
mv geth-ios-all-{{.Version}}/Geth.framework Frameworks
rm geth-ios-all-{{.Version}}
CMD
end