Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

external/ci: add darwin builds #27

Open
Thinkofname opened this issue May 20, 2015 · 5 comments
Open

external/ci: add darwin builds #27

Thinkofname opened this issue May 20, 2015 · 5 comments

Comments

@Thinkofname
Copy link
Owner

Would be great to add darwin/MacOS builds to the ci so they wouldn't have to build it themselves but i've yet to find a way to cross compile to darwin from linux like I do with the windows builds.

@suedadam
Copy link

Using
https://github.com/davecheney/golang-crosscompile
allows for you to build it for darwin 32bit and 64bit via
go-crosscompile-build darwin/386
go-crosscompile-build darwin/amd64

@Thinkofname
Copy link
Owner Author

We need cgo though which requires a compatible compiler

@suedadam
Copy link

I believe that is still possible but you'll need to modify the build.go file to comment out any checks involved with cross compiling cgo. I'll look a bit more later and see what I can find on the topic.

@lenovouser
Copy link
Contributor

Here are some pretty neat compiling scripts from Syncthing:
They seem even to create Linux .deb, OSX .pkg and Windows .msi installer scripts.
They are open-sourced under the Mozilla MPL. Maybe they are helpful to you :)

build.go

// Copyright (C) 2014 The Syncthing Authors.
//
// 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/.

// +build ignore

package main

import (
  "archive/tar"
  "archive/zip"
  "bytes"
  "compress/gzip"
  "crypto/md5"
  "flag"
  "fmt"
  "io"
  "io/ioutil"
  "log"
  "os"
  "os/exec"
  "os/user"
  "path/filepath"
  "regexp"
  "runtime"
  "strconv"
  "strings"
  "time"
)

var (
  versionRe = regexp.MustCompile(`-[0-9]{1,3}-g[0-9a-f]{5,10}`)
  goarch    string
  goos      string
  noupgrade bool
  version   string
  race      bool
)

const minGoVersion = 1.3

func main() {
  log.SetOutput(os.Stdout)
  log.SetFlags(0)

  if os.Getenv("GOPATH") == "" {
      cwd, err := os.Getwd()
      if err != nil {
          log.Fatal(err)
      }
      gopath := filepath.Clean(filepath.Join(cwd, "../../../../"))
      log.Println("GOPATH is", gopath)
      os.Setenv("GOPATH", gopath)
  }
  os.Setenv("PATH", fmt.Sprintf("%s%cbin%c%s", os.Getenv("GOPATH"), os.PathSeparator, os.PathListSeparator, os.Getenv("PATH")))

  flag.StringVar(&goarch, "goarch", runtime.GOARCH, "GOARCH")
  flag.StringVar(&goos, "goos", runtime.GOOS, "GOOS")
  flag.BoolVar(&noupgrade, "no-upgrade", noupgrade, "Disable upgrade functionality")
  flag.StringVar(&version, "version", getVersion(), "Set compiled in version string")
  flag.BoolVar(&race, "race", race, "Use race detector")
  flag.Parse()

  switch goarch {
  case "386", "amd64", "arm":
      break
  default:
      log.Printf("Unknown goarch %q; proceed with caution!", goarch)
  }

  checkRequiredGoVersion()

  if flag.NArg() == 0 {
      var tags []string
      if noupgrade {
          tags = []string{"noupgrade"}
      }
      install("./cmd/...", tags)

      vet("./cmd/syncthing")
      vet("./internal/...")
      lint("./cmd/syncthing")
      lint("./internal/...")
      return
  }

  for _, cmd := range flag.Args() {
      switch cmd {
      case "setup":
          setup()

      case "install":
          pkg := "./cmd/..."
          var tags []string
          if noupgrade {
              tags = []string{"noupgrade"}
          }
          install(pkg, tags)

      case "build":
          pkg := "./cmd/syncthing"
          var tags []string
          if noupgrade {
              tags = []string{"noupgrade"}
          }
          build(pkg, tags)

      case "test":
          test("./...")

      case "bench":
          bench("./...")

      case "assets":
          assets()

      case "xdr":
          xdr()

      case "translate":
          translate()

      case "transifex":
          transifex()

      case "deps":
          deps()

      case "tar":
          buildTar()

      case "zip":
          buildZip()

      case "deb":
          buildDeb()

      case "clean":
          clean()

      case "vet":
          vet("./cmd/syncthing")
          vet("./internal/...")

      case "lint":
          lint("./cmd/syncthing")
          lint("./internal/...")

      default:
          log.Fatalf("Unknown command %q", cmd)
      }
  }
}

func checkRequiredGoVersion() {
  ver := run("go", "version")
  re := regexp.MustCompile(`go version go(\d+\.\d+)`)
  if m := re.FindSubmatch(ver); len(m) == 2 {
      vs := string(m[1])
      // This is a standard go build. Verify that it's new enough.
      f, err := strconv.ParseFloat(vs, 64)
      if err != nil {
          log.Printf("*** Couldn't parse Go version out of %q.\n*** This isn't known to work, proceed on your own risk.", vs)
          return
      }
      if f < minGoVersion {
          log.Fatalf("*** Go version %.01f is less than required %.01f.\n*** This is known not to work, not proceeding.", f, minGoVersion)
      }
  } else {
      log.Printf("*** Unknown Go version %q.\n*** This isn't known to work, proceed on your own risk.", ver)
  }
}

func setup() {
  runPrint("go", "get", "-v", "golang.org/x/tools/cmd/cover")
  runPrint("go", "get", "-v", "golang.org/x/tools/cmd/vet")
  runPrint("go", "get", "-v", "golang.org/x/net/html")
  runPrint("go", "get", "-v", "github.com/tools/godep")
}

func test(pkg string) {
  setBuildEnv()
  runPrint("go", "test", "-short", "-timeout", "60s", pkg)
}

func bench(pkg string) {
  setBuildEnv()
  runPrint("go", "test", "-run", "NONE", "-bench", ".", pkg)
}

func install(pkg string, tags []string) {
  os.Setenv("GOBIN", "./bin")
  args := []string{"install", "-v", "-ldflags", ldflags()}
  if len(tags) > 0 {
      args = append(args, "-tags", strings.Join(tags, ","))
  }
  if race {
      args = append(args, "-race")
  }
  args = append(args, pkg)
  setBuildEnv()
  runPrint("go", args...)
}

func build(pkg string, tags []string) {
  binary := "syncthing"
  if goos == "windows" {
      binary += ".exe"
  }

  rmr(binary, binary+".md5")
  args := []string{"build", "-ldflags", ldflags()}
  if len(tags) > 0 {
      args = append(args, "-tags", strings.Join(tags, ","))
  }
  if race {
      args = append(args, "-race")
  }
  args = append(args, pkg)
  setBuildEnv()
  runPrint("go", args...)

  // Create an md5 checksum of the binary, to be included in the archive for
  // automatic upgrades.
  err := md5File(binary)
  if err != nil {
      log.Fatal(err)
  }
}

func buildTar() {
  name := archiveName()
  var tags []string
  if noupgrade {
      tags = []string{"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"},
      {src: "syncthing.md5", dst: name + "/syncthing.md5"},
  }

  for _, file := range listFiles("etc") {
      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)})
  }

  tarGz(filename, files)
  log.Println(filename)
}

func buildZip() {
  name := archiveName()
  var tags []string
  if noupgrade {
      tags = []string{"noupgrade"}
      name += "-noupgrade"
  }
  build("./cmd/syncthing", tags)
  filename := name + ".zip"
  files := []archiveFile{
      {src: "README.md", dst: name + "/README.txt"},
      {src: "LICENSE", dst: name + "/LICENSE.txt"},
      {src: "AUTHORS", dst: name + "/AUTHORS.txt"},
      {src: "syncthing.exe", dst: name + "/syncthing.exe"},
      {src: "syncthing.exe.md5", dst: name + "/syncthing.exe.md5"},
  }

  for _, file := range listFiles("extra") {
      files = append(files, archiveFile{src: file, dst: name + "/" + filepath.Base(file)})
  }

  zipFile(filename, files)
  log.Println(filename)
}

func buildDeb() {
  os.RemoveAll("deb")

  // "goarch" here is set to whatever the Debian packages expect. We correct
  // "it to what we actually know how to build and keep the Debian variant
  // "name in "debarch".
  debarch := goarch
  switch goarch {
  case "i386":
      goarch = "386"
  case "armel", "armhf":
      goarch = "arm"
  }

  build("./cmd/syncthing", []string{"noupgrade"})

  files := []archiveFile{
      {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: "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},
  }

  for _, file := range listFiles("extra") {
      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 {
          log.Fatal(err)
      }
  }

  control := `Package: syncthing
Architecture: {{arch}}
Depends: libc6
Version: {{version}}
Maintainer: Syncthing Release Management <release@syncthing.net>
Description: Open Source Continuous File Synchronization
  Syncthing does bidirectional synchronization of files between two or
  more computers.
`
  changelog := `syncthing ({{version}}); urgency=medium

  * Packaging of {{version}}.

 -- Jakob Borg <jakob@nym.se>  {{date}}
`

  control = strings.Replace(control, "{{arch}}", debarch, -1)
  control = strings.Replace(control, "{{version}}", version[1:], -1)
  changelog = strings.Replace(changelog, "{{arch}}", debarch, -1)
  changelog = strings.Replace(changelog, "{{version}}", version[1:], -1)
  changelog = strings.Replace(changelog, "{{date}}", time.Now().Format(time.RFC1123), -1)

  os.MkdirAll("deb/DEBIAN", 0755)
  ioutil.WriteFile("deb/DEBIAN/control", []byte(control), 0644)
  ioutil.WriteFile("deb/DEBIAN/compat", []byte("9\n"), 0644)
  ioutil.WriteFile("deb/DEBIAN/changelog", []byte(changelog), 0644)

}

func copyFile(src, dst string, perm os.FileMode) error {
  dstDir := filepath.Dir(dst)
  os.MkdirAll(dstDir, 0755) // ignore error
  srcFd, err := os.Open(src)
  if err != nil {
      return err
  }
  defer srcFd.Close()
  dstFd, err := os.OpenFile(dst, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, perm)
  if err != nil {
      return err
  }
  defer dstFd.Close()
  _, err = io.Copy(dstFd, srcFd)
  return err
}

func listFiles(dir string) []string {
  var res []string
  filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error {
      if err != nil {
          return err
      }
      if fi.Mode().IsRegular() {
          res = append(res, path)
      }
      return nil
  })
  return res
}

func setBuildEnv() {
  os.Setenv("GOOS", goos)
  os.Setenv("GOARCH", goarch)
  wd, err := os.Getwd()
  if err != nil {
      log.Println("Warning: can't determine current dir:", err)
      log.Println("Build might not work as expected")
  }
  os.Setenv("GOPATH", fmt.Sprintf("%s%c%s", filepath.Join(wd, "Godeps", "_workspace"), os.PathListSeparator, os.Getenv("GOPATH")))
  log.Println("GOPATH=" + os.Getenv("GOPATH"))
}

func assets() {
  setBuildEnv()
  runPipe("internal/auto/gui.files.go", "go", "run", "cmd/genassets/main.go", "gui")
}

func xdr() {
  runPrint("go", "generate", "./internal/discover", "./internal/db")
}

func translate() {
  os.Chdir("gui/assets/lang")
  runPipe("lang-en-new.json", "go", "run", "../../../cmd/translate/main.go", "lang-en.json", "../../index.html")
  os.Remove("lang-en.json")
  err := os.Rename("lang-en-new.json", "lang-en.json")
  if err != nil {
      log.Fatal(err)
  }
  os.Chdir("../../..")
}

func transifex() {
  os.Chdir("gui/assets/lang")
  runPrint("go", "run", "../../../cmd/transifexdl/main.go")
  os.Chdir("../../..")
  assets()
}

func deps() {
  rmr("Godeps")
  runPrint("godep", "save", "./cmd/...")
}

func clean() {
  rmr("bin", "Godeps/_workspace/pkg", "Godeps/_workspace/bin")
  rmr(filepath.Join(os.Getenv("GOPATH"), fmt.Sprintf("pkg/%s_%s/github.com/syncthing", goos, goarch)))
}

func ldflags() string {
  var b bytes.Buffer
  b.WriteString("-w")
  b.WriteString(fmt.Sprintf(" -X main.Version %s", version))
  b.WriteString(fmt.Sprintf(" -X main.BuildStamp %d", buildStamp()))
  b.WriteString(fmt.Sprintf(" -X main.BuildUser %s", buildUser()))
  b.WriteString(fmt.Sprintf(" -X main.BuildHost %s", buildHost()))
  b.WriteString(fmt.Sprintf(" -X main.BuildEnv %s", buildEnvironment()))
  return b.String()
}

func rmr(paths ...string) {
  for _, path := range paths {
      log.Println("rm -r", path)
      os.RemoveAll(path)
  }
}

func getReleaseVersion() (string, error) {
  fd, err := os.Open("RELEASE")
  if err != nil {
      return "", err
  }
  defer fd.Close()

  bs, err := ioutil.ReadAll(fd)
  if err != nil {
      return "", err
  }
  return string(bytes.TrimSpace(bs)), nil
}

func getGitVersion() (string, error) {
  v, err := runError("git", "describe", "--always", "--dirty")
  if err != nil {
      return "", err
  }
  v = versionRe.ReplaceAllFunc(v, func(s []byte) []byte {
      s[0] = '+'
      return s
  })
  return string(v), nil
}

func getVersion() string {
  // First try for a RELEASE file,
  if ver, err := getReleaseVersion(); err == nil {
      return ver
  }
  // ... then see if we have a Git tag.
  if ver, err := getGitVersion(); err == nil {
      return ver
  }
  // This seems to be a dev build.
  return "unknown-dev"
}

func buildStamp() int64 {
  bs, err := runError("git", "show", "-s", "--format=%ct")
  if err != nil {
      return time.Now().Unix()
  }
  s, _ := strconv.ParseInt(string(bs), 10, 64)
  return s
}

func buildUser() string {
  u, err := user.Current()
  if err != nil {
      return "unknown-user"
  }
  return strings.Replace(u.Username, " ", "-", -1)
}

func buildHost() string {
  h, err := os.Hostname()
  if err != nil {
      return "unknown-host"
  }
  return h
}

func buildEnvironment() string {
  if v := os.Getenv("ENVIRONMENT"); len(v) > 0 {
      return v
  }
  return "default"
}

func buildArch() string {
  os := goos
  if os == "darwin" {
      os = "macosx"
  }
  return fmt.Sprintf("%s-%s", os, goarch)
}

func archiveName() string {
  return fmt.Sprintf("syncthing-%s-%s", buildArch(), version)
}

func run(cmd string, args ...string) []byte {
  bs, err := runError(cmd, args...)
  if err != nil {
      log.Println(cmd, strings.Join(args, " "))
      log.Println(string(bs))
      log.Fatal(err)
  }
  return bytes.TrimSpace(bs)
}

func runError(cmd string, args ...string) ([]byte, error) {
  ecmd := exec.Command(cmd, args...)
  bs, err := ecmd.CombinedOutput()
  return bytes.TrimSpace(bs), err
}

func runPrint(cmd string, args ...string) {
  log.Println(cmd, strings.Join(args, " "))
  ecmd := exec.Command(cmd, args...)
  ecmd.Stdout = os.Stdout
  ecmd.Stderr = os.Stderr
  err := ecmd.Run()
  if err != nil {
      log.Fatal(err)
  }
}

func runPipe(file, cmd string, args ...string) {
  log.Println(cmd, strings.Join(args, " "), ">", file)
  fd, err := os.Create(file)
  if err != nil {
      log.Fatal(err)
  }
  ecmd := exec.Command(cmd, args...)
  ecmd.Stdout = fd
  ecmd.Stderr = os.Stderr
  err = ecmd.Run()
  if err != nil {
      log.Fatal(err)
  }
  fd.Close()
}

type archiveFile struct {
  src  string
  dst  string
  perm os.FileMode
}

func tarGz(out string, files []archiveFile) {
  fd, err := os.Create(out)
  if err != nil {
      log.Fatal(err)
  }

  gw := gzip.NewWriter(fd)
  tw := tar.NewWriter(gw)

  for _, f := range files {
      sf, err := os.Open(f.src)
      if err != nil {
          log.Fatal(err)
      }

      info, err := sf.Stat()
      if err != nil {
          log.Fatal(err)
      }
      h := &tar.Header{
          Name:    f.dst,
          Size:    info.Size(),
          Mode:    int64(info.Mode()),
          ModTime: info.ModTime(),
      }

      err = tw.WriteHeader(h)
      if err != nil {
          log.Fatal(err)
      }
      _, err = io.Copy(tw, sf)
      if err != nil {
          log.Fatal(err)
      }
      sf.Close()
  }

  err = tw.Close()
  if err != nil {
      log.Fatal(err)
  }
  err = gw.Close()
  if err != nil {
      log.Fatal(err)
  }
  err = fd.Close()
  if err != nil {
      log.Fatal(err)
  }
}

func zipFile(out string, files []archiveFile) {
  fd, err := os.Create(out)
  if err != nil {
      log.Fatal(err)
  }

  zw := zip.NewWriter(fd)

  for _, f := range files {
      sf, err := os.Open(f.src)
      if err != nil {
          log.Fatal(err)
      }

      info, err := sf.Stat()
      if err != nil {
          log.Fatal(err)
      }

      fh, err := zip.FileInfoHeader(info)
      if err != nil {
          log.Fatal(err)
      }
      fh.Name = f.dst
      fh.Method = zip.Deflate

      if strings.HasSuffix(f.dst, ".txt") {
          // Text file. Read it and convert line endings.
          bs, err := ioutil.ReadAll(sf)
          if err != nil {
              log.Fatal(err)
          }
          bs = bytes.Replace(bs, []byte{'\n'}, []byte{'\n', '\r'}, -1)
          fh.UncompressedSize = uint32(len(bs))
          fh.UncompressedSize64 = uint64(len(bs))

          of, err := zw.CreateHeader(fh)
          if err != nil {
              log.Fatal(err)
          }
          of.Write(bs)
      } else {
          // Binary file. Copy verbatim.
          of, err := zw.CreateHeader(fh)
          if err != nil {
              log.Fatal(err)
          }
          _, err = io.Copy(of, sf)
          if err != nil {
              log.Fatal(err)
          }
      }
  }

  err = zw.Close()
  if err != nil {
      log.Fatal(err)
  }
  err = fd.Close()
  if err != nil {
      log.Fatal(err)
  }
}

func md5File(file string) error {
  fd, err := os.Open(file)
  if err != nil {
      return err
  }
  defer fd.Close()

  h := md5.New()
  _, err = io.Copy(h, fd)
  if err != nil {
      return err
  }

  out, err := os.Create(file + ".md5")
  if err != nil {
      return err
  }

  _, err = fmt.Fprintf(out, "%x\n", h.Sum(nil))
  if err != nil {
      return err
  }

  return out.Close()
}

func vet(pkg string) {
  bs, err := runError("go", "vet", pkg)
  if err != nil && err.Error() == "exit status 3" || bytes.Contains(bs, []byte("no such tool \"vet\"")) {
      // Go said there is no go vet
      log.Println(`- No go vet, no vetting. Try "go get -u golang.org/x/tools/cmd/vet".`)
      return
  }

  falseAlarmComposites := regexp.MustCompile("composite literal uses unkeyed fields")
  exitStatus := regexp.MustCompile("exit status 1")
  for _, line := range bytes.Split(bs, []byte("\n")) {
      if falseAlarmComposites.Match(line) || exitStatus.Match(line) {
          continue
      }
      log.Printf("%s", line)
  }
}

func lint(pkg string) {
  bs, err := runError("golint", pkg)
>     if err != nil {
      log.Println(`- No golint, not linting. Try "go get -u github.com/golang/lint/golint".`)
      return
  }

  analCommentPolicy := regexp.MustCompile(`exported (function|method|const|type|var) [^\s]+ should have comment`)
  for _, line := range bytes.Split(bs, []byte("\n")) {
      if analCommentPolicy.Match(line) {
          continue
      }
      log.Printf("%s", line)
  }
}

and

build.sh

#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'

STTRACE=${STTRACE:-}

> case "${1:-default}" in
  default)
      go run build.go
      ;;

  clean)
      go run build.go "$1"
      ;;

  test)
      ulimit -t 60 &>/dev/null || true
      ulimit -d 512000 &>/dev/null || true
      ulimit -m 512000 &>/dev/null || true
      go run build.go test
      ;;

  bench)
      LOGGER_DISCARD=1 go run build.go bench | go run benchfilter.go
      ;;

  tar)
      go run build.go "$1"
      ;;

  deps)
      go run build.go "$1"
      ;;

  assets)
      go run build.go "$1"
      ;;

  xdr)
      go run build.go "$1"
      ;;

  translate)
      go run build.go "$1"
      ;;

  prerelease)
      go run build.go transifex
      git add -A gui/assets/ internal/auto/
      pushd man ; ./refresh.sh ; popd
      git add -A man
      echo
      echo Changelog:
      go run changelog.go
      ;;

  noupgrade)
      go run build.go -no-upgrade tar
      ;;

  all)
      go run build.go -goos darwin -goarch amd64 tar
      go run build.go -goos darwin -goarch 386 tar

      go run build.go -goos dragonfly -goarch 386 tar
      go run build.go -goos dragonfly -goarch amd64 tar

      go run build.go -goos freebsd -goarch 386 tar
      go run build.go -goos freebsd -goarch amd64 tar

      go run build.go -goos linux -goarch 386 tar
      go run build.go -goos linux -goarch amd64 tar
      go run build.go -goos linux -goarch arm tar

      go run build.go -goos netbsd -goarch 386 tar
      go run build.go -goos netbsd -goarch amd64 tar

      go run build.go -goos openbsd -goarch 386 tar
      go run build.go -goos openbsd -goarch amd64 tar

      go run build.go -goos solaris -goarch amd64 tar

      go run build.go -goos windows -goarch 386 zip
      go run build.go -goos windows -goarch amd64 zip
      ;;

  setup)
      echo "Don't worry, just build."
      ;;

  test-cov)
      ulimit -t 600 &>/dev/null || true
      ulimit -d 512000 &>/dev/null || true
      ulimit -m 512000 &>/dev/null || true

      go get github.com/axw/gocov/gocov
      go get github.com/AlekSi/gocov-xml

      echo "mode: set" > coverage.out
      fail=0

      # For every package in the repo
      for dir in $(go list ./...) ; do
          # run the tests
          godep go test -coverprofile=profile.out $dir
          if [ -f profile.out ] ; then
              # and if there was test output, append it to coverage.out
              grep -v "mode: set" profile.out >> coverage.out
              rm profile.out
          fi
      done

      gocov convert coverage.out | gocov-xml > coverage.xml

      # This is usually run from within Jenkins. If it is, we need to
      # tweak the paths in coverage.xml so cobertura finds the
      # source.
      if [[ "${WORKSPACE:-default}" != "default" ]] ; then
          sed "s#$WORKSPACE##g" < coverage.xml > coverage.xml.new && mv coverage.xml.new coverage.xml
      fi
      ;;

  docker-all)
      docker run --rm -h syncthing-builder -u $(id -u) -t \
          -v $(pwd):/go/src/github.com/syncthing/syncthing \
          -w /go/src/github.com/syncthing/syncthing \
          -e "STTRACE=$STTRACE" \
          syncthing/build:latest \
          sh -c './build.sh clean \
              && ./build.sh test-cov \
              && ./build.sh bench \
              && ./build.sh all'
      ;;

  docker-test)
      docker run --rm -h syncthing-builder -u $(id -u) -t \
          -v $(pwd):/go/src/github.com/syncthing/syncthing \
          -w /go/src/github.com/syncthing/syncthing \
          -e "STTRACE=$STTRACE" \
          syncthing/build:latest \
          sh -euxc './build.sh clean \
              && go run build.go -race \
              && export GOPATH=$(pwd)/Godeps/_workspace:$GOPATH \
              && cd test \
              && go test -tags integration -v -timeout 90m -short \
              && git clean -fxd .'
      ;;

  docker-lint)
      docker run --rm -h syncthing-builder -u $(id -u) -t \
          -v $(pwd):/go/src/github.com/syncthing/syncthing \
          -w /go/src/github.com/syncthing/syncthing \
          -e "STTRACE=$STTRACE" \
          syncthing/build:latest \
          sh -euxc 'go run build.go lint'
      ;;


  docker-vet)
      docker run --rm -h syncthing-builder -u $(id -u) -t \
          -v $(pwd):/go/src/github.com/syncthing/syncthing \
          -w /go/src/github.com/syncthing/syncthing \
          -e "STTRACE=$STTRACE" \
          syncthing/build:latest \
          sh -euxc 'go run build.go vet'
      ;;

  *)
      echo "Unknown build command $1"
      ;;
esac

@Thinkofname
Copy link
Owner Author

While its a nice script it doesn't solve the issue, nor does removing cgo checks. cgo getting disabled on cross compile can be overridden with with CGO_ENABLED=1 (I already do this for windows builds on ci) the issue comes in when it tries to invoke gcc/clang and fails because they aren't the for mac (gcc) or missing headers (clang) and have linker issues (clang apparently uses gcc as its linker). Unless I can get something like mingw (Which I use for the windows builds on linux) for darwin I don't see how I can get this working.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants