build: Parameterize build targets

This commit is contained in:
Jakob Borg 2016-04-06 23:18:30 +02:00 committed by Audrius Butkevicius
parent 492e92d65d
commit 4f5d0b46f7
6 changed files with 187 additions and 137 deletions

1
.gitignore vendored
View File

@ -1,5 +1,6 @@
syncthing syncthing
!gui/syncthing !gui/syncthing
!debian/syncthing
!Godeps/_workspace/src/github.com/syncthing !Godeps/_workspace/src/github.com/syncthing
syncthing.exe syncthing.exe
*.tar.gz *.tar.gz

321
build.go
View File

@ -40,6 +40,76 @@ var (
race bool race bool
) )
type target struct {
name string
buildPkg string
binaryName string
archiveFiles []archiveFile
debianFiles []archiveFile
}
type archiveFile struct {
src string
dst string
perm os.FileMode
}
var targets = map[string]target{
"all": {
// Only valid for the "build" and "install" commands as it lacks all
// the archive creation stuff.
buildPkg: "./cmd/...",
},
"syncthing": {
// The default target for "build", "install", "tar", "zip", "deb", etc.
name: "syncthing",
buildPkg: "./cmd/syncthing",
binaryName: "syncthing", // .exe will be added automatically for Windows builds
archiveFiles: []archiveFile{
{src: "{{binary}}", dst: "{{binary}}", perm: 0755},
{src: "README.md", dst: "README.txt", perm: 0644},
{src: "LICENSE", dst: "LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "AUTHORS.txt", perm: 0644},
// All files from etc/ and extra/ added automatically in init().
},
debianFiles: []archiveFile{
{src: "{{binary}}", dst: "deb/usr/bin/{{binary}}", perm: 0755},
{src: "README.md", dst: "deb/usr/share/doc/syncthing/README.txt", perm: 0644},
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing/LICENSE.txt", perm: 0644},
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing/AUTHORS.txt", perm: 0644},
{src: "man/syncthing.1", dst: "deb/usr/share/man/man1/syncthing.1", perm: 0644},
{src: "man/syncthing-config.5", dst: "deb/usr/share/man/man5/syncthing-config.5", perm: 0644},
{src: "man/syncthing-stignore.5", dst: "deb/usr/share/man/man5/syncthing-stignore.5", perm: 0644},
{src: "man/syncthing-device-ids.7", dst: "deb/usr/share/man/man7/syncthing-device-ids.7", perm: 0644},
{src: "man/syncthing-event-api.7", dst: "deb/usr/share/man/man7/syncthing-event-api.7", perm: 0644},
{src: "man/syncthing-faq.7", dst: "deb/usr/share/man/man7/syncthing-faq.7", perm: 0644},
{src: "man/syncthing-networking.7", dst: "deb/usr/share/man/man7/syncthing-networking.7", perm: 0644},
{src: "man/syncthing-rest-api.7", dst: "deb/usr/share/man/man7/syncthing-rest-api.7", perm: 0644},
{src: "man/syncthing-security.7", dst: "deb/usr/share/man/man7/syncthing-security.7", perm: 0644},
{src: "man/syncthing-versioning.7", dst: "deb/usr/share/man/man7/syncthing-versioning.7", perm: 0644},
{src: "etc/linux-systemd/system/syncthing@.service", dst: "deb/lib/systemd/system/syncthing@.service", perm: 0644},
{src: "etc/linux-systemd/system/syncthing-resume.service", dst: "deb/lib/systemd/system/syncthing-resume.service", perm: 0644},
{src: "etc/linux-systemd/user/syncthing.service", dst: "deb/usr/lib/systemd/user/syncthing.service", perm: 0644},
},
},
}
func init() {
// The "syncthing" target includes a few more files found in the "etc"
// and "extra" dirs.
syncthingPkg := targets["syncthing"]
for _, file := range listFiles("etc") {
syncthingPkg.archiveFiles = append(syncthingPkg.archiveFiles, archiveFile{src: file, dst: file, perm: 0644})
}
for _, file := range listFiles("extra") {
syncthingPkg.archiveFiles = append(syncthingPkg.archiveFiles, archiveFile{src: file, dst: file, perm: 0644})
}
for _, file := range listFiles("extra") {
syncthingPkg.debianFiles = append(syncthingPkg.debianFiles, archiveFile{src: file, dst: "deb/usr/share/doc/syncthing/" + filepath.Base(file), perm: 0644})
}
targets["syncthing"] = syncthingPkg
}
const minGoVersion = 1.3 const minGoVersion = 1.3
func main() { func main() {
@ -81,12 +151,15 @@ func main() {
goVersion, _ = checkRequiredGoVersion() goVersion, _ = checkRequiredGoVersion()
// Invoking build.go with no parameters at all is equivalent to "go run
// build.go install all" as that builds everything (incrementally),
// which is what you want for maximum error checking during development.
if flag.NArg() == 0 { if flag.NArg() == 0 {
var tags []string var tags []string
if noupgrade { if noupgrade {
tags = []string{"noupgrade"} tags = []string{"noupgrade"}
} }
install("./cmd/...", tags) install(targets["all"], tags)
vet("./cmd/syncthing") vet("./cmd/syncthing")
vet("./lib/...") vet("./lib/...")
@ -95,68 +168,77 @@ func main() {
return return
} }
for _, cmd := range flag.Args() { // Otherwise, with any command given but not a target, the target is
switch cmd { // "syncthing". So "go run build.go install" is "go run build.go install
case "setup": // syncthing" etc.
setup() targetName := "syncthing"
if flag.NArg() > 1 {
targetName = flag.Arg(1)
}
target, ok := targets[targetName]
if !ok {
log.Fatalln("Unknown target", target)
}
case "install": cmd := flag.Arg(0)
pkg := "./cmd/..." switch cmd {
var tags []string case "setup":
if noupgrade { setup()
tags = []string{"noupgrade"}
}
install(pkg, tags)
case "build": case "install":
pkg := "./cmd/syncthing" var tags []string
var tags []string if noupgrade {
if noupgrade { tags = []string{"noupgrade"}
tags = []string{"noupgrade"}
}
build(pkg, tags)
case "test":
test("./lib/...", "./cmd/...")
case "bench":
bench("./lib/...", "./cmd/...")
case "assets":
rebuildAssets()
case "xdr":
xdr()
case "translate":
translate()
case "transifex":
transifex()
case "tar":
buildTar()
case "zip":
buildZip()
case "deb":
buildDeb()
case "clean":
clean()
case "vet":
vet("./cmd/syncthing")
vet("./lib/...")
case "lint":
lint("./cmd/syncthing")
lint("./lib/...")
default:
log.Fatalf("Unknown command %q", cmd)
} }
install(target, tags)
case "build":
var tags []string
if noupgrade {
tags = []string{"noupgrade"}
}
build(target, tags)
case "test":
test("./lib/...", "./cmd/...")
case "bench":
bench("./lib/...", "./cmd/...")
case "assets":
rebuildAssets()
case "xdr":
xdr()
case "translate":
translate()
case "transifex":
transifex()
case "tar":
buildTar(target)
case "zip":
buildZip(target)
case "deb":
buildDeb(target)
case "clean":
clean()
case "vet":
vet("./cmd/syncthing")
vet("./lib/...")
case "lint":
lint("./cmd/syncthing")
lint("./lib/...")
default:
log.Fatalf("Unknown command %q", cmd)
} }
} }
@ -215,7 +297,7 @@ func bench(pkgs ...string) {
runPrint("go", append([]string{"test", "-run", "NONE", "-bench", "."}, pkgs...)...) runPrint("go", append([]string{"test", "-run", "NONE", "-bench", "."}, pkgs...)...)
} }
func install(pkg string, tags []string) { func install(target target, tags []string) {
lazyRebuildAssets() lazyRebuildAssets()
cwd, err := os.Getwd() cwd, err := os.Getwd()
@ -230,22 +312,17 @@ func install(pkg string, tags []string) {
if race { if race {
args = append(args, "-race") args = append(args, "-race")
} }
args = append(args, pkg) args = append(args, target.buildPkg)
os.Setenv("GOOS", goos) os.Setenv("GOOS", goos)
os.Setenv("GOARCH", goarch) os.Setenv("GOARCH", goarch)
runPrint("go", args...) runPrint("go", args...)
} }
func build(pkg string, tags []string) { func build(target target, tags []string) {
lazyRebuildAssets() lazyRebuildAssets()
binary := "syncthing" rmr(target.binaryName)
if goos == "windows" {
binary += ".exe"
}
rmr(binary)
args := []string{"build", "-i", "-v", "-ldflags", ldflags()} args := []string{"build", "-i", "-v", "-ldflags", ldflags()}
if len(tags) > 0 { if len(tags) > 0 {
args = append(args, "-tags", strings.Join(tags, ",")) args = append(args, "-tags", strings.Join(tags, ","))
@ -253,68 +330,62 @@ func build(pkg string, tags []string) {
if race { if race {
args = append(args, "-race") args = append(args, "-race")
} }
args = append(args, pkg) args = append(args, target.buildPkg)
os.Setenv("GOOS", goos) os.Setenv("GOOS", goos)
os.Setenv("GOARCH", goarch) os.Setenv("GOARCH", goarch)
runPrint("go", args...) runPrint("go", args...)
} }
func buildTar() { func buildTar(target target) {
name := archiveName() name := archiveName(target)
filename := name + ".tar.gz"
var tags []string var tags []string
if noupgrade { if noupgrade {
tags = []string{"noupgrade"} tags = []string{"noupgrade"}
name += "-noupgrade" name += "-noupgrade"
} }
build("./cmd/syncthing", tags)
filename := name + ".tar.gz"
files := []archiveFile{
{src: "README.md", dst: name + "/README.txt"},
{src: "LICENSE", dst: name + "/LICENSE.txt"},
{src: "AUTHORS", dst: name + "/AUTHORS.txt"},
{src: "syncthing", dst: name + "/syncthing"},
}
for _, file := range listFiles("etc") { build(target, tags)
files = append(files, archiveFile{src: file, dst: name + "/" + file})
}
for _, file := range listFiles("extra") {
files = append(files, archiveFile{src: file, dst: name + "/" + filepath.Base(file)})
}
if goos == "darwin" { if goos == "darwin" {
macosCodesign("syncthing") macosCodesign(target.binaryName)
} }
tarGz(filename, files)
for i := range target.archiveFiles {
target.archiveFiles[i].src = strings.Replace(target.archiveFiles[i].src, "{{binary}}", target.binaryName, 1)
target.archiveFiles[i].dst = strings.Replace(target.archiveFiles[i].dst, "{{binary}}", target.binaryName, 1)
}
tarGz(filename, target.archiveFiles)
log.Println(filename) log.Println(filename)
} }
func buildZip() { func buildZip(target target) {
name := archiveName() target.binaryName += ".exe"
name := archiveName(target)
filename := name + ".zip"
var tags []string var tags []string
if noupgrade { if noupgrade {
tags = []string{"noupgrade"} tags = []string{"noupgrade"}
name += "-noupgrade" name += "-noupgrade"
} }
build("./cmd/syncthing", tags)
filename := name + ".zip" build(target, tags)
files := []archiveFile{
{src: "README.md", dst: name + "/README.txt"}, for i := range target.archiveFiles {
{src: "LICENSE", dst: name + "/LICENSE.txt"}, target.archiveFiles[i].src = strings.Replace(target.archiveFiles[i].src, "{{binary}}", target.binaryName, 1)
{src: "AUTHORS", dst: name + "/AUTHORS.txt"}, target.archiveFiles[i].dst = strings.Replace(target.archiveFiles[i].dst, "{{binary}}", target.binaryName, 1)
{src: "syncthing.exe", dst: name + "/syncthing.exe"},
} }
for _, file := range listFiles("extra") { zipFile(filename, target.archiveFiles)
files = append(files, archiveFile{src: file, dst: name + "/" + filepath.Base(file)})
}
zipFile(filename, files)
log.Println(filename) log.Println(filename)
} }
func buildDeb() { func buildDeb(target target) {
os.RemoveAll("deb") os.RemoveAll("deb")
// "goarch" here is set to whatever the Debian packages expect. We correct // "goarch" here is set to whatever the Debian packages expect. We correct
@ -328,33 +399,14 @@ func buildDeb() {
goarch = "arm" goarch = "arm"
} }
build("./cmd/syncthing", []string{"noupgrade"}) build(target, []string{"noupgrade"})
files := []archiveFile{ for i := range target.debianFiles {
{src: "README.md", dst: "deb/usr/share/doc/syncthing/README.txt", perm: 0644}, target.debianFiles[i].src = strings.Replace(target.debianFiles[i].src, "{{binary}}", target.binaryName, 1)
{src: "LICENSE", dst: "deb/usr/share/doc/syncthing/LICENSE.txt", perm: 0644}, target.debianFiles[i].dst = strings.Replace(target.debianFiles[i].dst, "{{binary}}", target.binaryName, 1)
{src: "AUTHORS", dst: "deb/usr/share/doc/syncthing/AUTHORS.txt", perm: 0644},
{src: "syncthing", dst: "deb/usr/bin/syncthing", perm: 0755},
{src: "man/syncthing.1", dst: "deb/usr/share/man/man1/syncthing.1", perm: 0644},
{src: "man/syncthing-config.5", dst: "deb/usr/share/man/man5/syncthing-config.5", perm: 0644},
{src: "man/syncthing-stignore.5", dst: "deb/usr/share/man/man5/syncthing-stignore.5", perm: 0644},
{src: "man/syncthing-device-ids.7", dst: "deb/usr/share/man/man7/syncthing-device-ids.7", perm: 0644},
{src: "man/syncthing-event-api.7", dst: "deb/usr/share/man/man7/syncthing-event-api.7", perm: 0644},
{src: "man/syncthing-faq.7", dst: "deb/usr/share/man/man7/syncthing-faq.7", perm: 0644},
{src: "man/syncthing-networking.7", dst: "deb/usr/share/man/man7/syncthing-networking.7", perm: 0644},
{src: "man/syncthing-rest-api.7", dst: "deb/usr/share/man/man7/syncthing-rest-api.7", perm: 0644},
{src: "man/syncthing-security.7", dst: "deb/usr/share/man/man7/syncthing-security.7", perm: 0644},
{src: "man/syncthing-versioning.7", dst: "deb/usr/share/man/man7/syncthing-versioning.7", perm: 0644},
{src: "etc/linux-systemd/system/syncthing@.service", dst: "deb/lib/systemd/system/syncthing@.service", perm: 0644},
{src: "etc/linux-systemd/system/syncthing-resume.service", dst: "deb/lib/systemd/system/syncthing-resume.service", perm: 0644},
{src: "etc/linux-systemd/user/syncthing.service", dst: "deb/usr/lib/systemd/user/syncthing.service", perm: 0644},
} }
for _, file := range listFiles("extra") { for _, af := range target.debianFiles {
files = append(files, archiveFile{src: file, dst: "deb/usr/share/doc/syncthing/" + filepath.Base(file), perm: 0644})
}
for _, af := range files {
if err := copyFile(af.src, af.dst, af.perm); err != nil { if err := copyFile(af.src, af.dst, af.perm); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -363,11 +415,14 @@ func buildDeb() {
os.MkdirAll("deb/DEBIAN", 0755) os.MkdirAll("deb/DEBIAN", 0755)
data := map[string]string{ data := map[string]string{
"name": target.name,
"arch": debarch, "arch": debarch,
"version": version[1:], "version": version[1:],
"date": time.Now().Format(time.RFC1123), "date": time.Now().Format(time.RFC1123),
} }
for _, file := range listFiles("debian") {
debTemplateFiles := append(listFiles("debian/common"), listFiles("debian/"+target.name)...)
for _, file := range debTemplateFiles {
tpl, err := template.New(filepath.Base(file)).ParseFiles(file) tpl, err := template.New(filepath.Base(file)).ParseFiles(file)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -634,8 +689,8 @@ func buildArch() string {
return fmt.Sprintf("%s-%s", os, goarch) return fmt.Sprintf("%s-%s", os, goarch)
} }
func archiveName() string { func archiveName(target target) string {
return fmt.Sprintf("syncthing-%s-%s", buildArch(), version) return fmt.Sprintf("%s-%s-%s", target.name, buildArch(), version)
} }
func run(cmd string, args ...string) []byte { func run(cmd string, args ...string) []byte {
@ -681,12 +736,6 @@ func runPipe(file, cmd string, args ...string) {
fd.Close() fd.Close()
} }
type archiveFile struct {
src string
dst string
perm os.FileMode
}
func tarGz(out string, files []archiveFile) { func tarGz(out string, files []archiveFile) {
fd, err := os.Create(out) fd, err := os.Create(out)
if err != nil { if err != nil {

View File

@ -1,4 +1,4 @@
syncthing ({{.version}}); urgency=medium {{.name}} ({{.version}}); urgency=medium
* Packaging of {{.version}}. * Packaging of {{.version}}.