view master.cfg @ 1:97e7b7963dc9

make test log filtering work again
author John W. Eaton <jwe@octave.org>
date Tue, 12 Jun 2018 21:14:47 +0000
parents 4ad92f00bca5
children f77e7e92cc95
line wrap: on
line source

## -*- python -*-
## ex: set syntax=python:

## This is a sample buildmaster config file. It must be installed as
## 'master.cfg' in your buildmaster's base directory.

## This is the dictionary that the buildmaster pays attention to. We
## also use a shorter alias to save typing.

c = BuildmasterConfig = {}

## WORKERS

## The 'worker' list defines the set of recognized workers. Each
## element is a Worker object, specifying a unique worker name and
## password.  The same worker name and password must be configured on
## the worker.

from buildbot.worker import Worker

## Not in hg archive because it contains password and system configuration info.
import octave_buildbot_config

c["workers"] = []

for worker, info in octave_buildbot_config.workers.iteritems ():
  c["workers"].append (Worker (worker, info["pass"], max_builds = info["max_builds"]))

## 'protocols' contains information about protocols which master will
## use for communicating with workers.  You must define at least 'port'
## option that workers could connect to your master with this protocol.
## 'port' must match the value configured into the workers (with
## their --master option)

c["protocols"] = { "pb" : { "port" : 9990 }}

## SOURCES

## The main mercurial repository server. This machines pings the
## PBChangeSource. The workers should pull from it, to make
## sure they are in sync.

octave_hg_repo = "https://hg.savannah.gnu.org/hgweb/octave"
## NOTE: We need this second URL for the Octave sources because
## of a bug in buildbot that won't allow two hg poller instances
## for the same URL.  If that were possible, then we could have
## one URL for both the stable and default branches.
stable_octave_hg_repo = "http://hg.octave.org/octave"
mxe_octave_hg_repo = "http://hg.octave.org/mxe-octave"

## CHANGESOURCES

## the 'change_source' setting tells the buildmaster how it should
## find out about source code changes.  Here we point to the buildbot
## clone of Octave.

from buildbot.changes.hgpoller import HgPoller

c["change_source"] = []

c["change_source"].append (HgPoller (project = "octave",
                                     repourl = octave_hg_repo,
                                     workdir = "octave-hg-repo",
                                     pollinterval = 5*60))

c["change_source"].append (HgPoller (project = "stable octave",
                                     branch = "stable",
                                     repourl = stable_octave_hg_repo,
                                     workdir = "stable-octave-hg-repo",
                                     pollinterval = 5*60))

c["change_source"].append (HgPoller (project = "mxe-octave",
                                     repourl = mxe_octave_hg_repo,
                                     workdir = "mxe-octave-hg-repo",
                                     pollinterval = 15*60))

## FILTERS

from buildbot.changes import filter

octave_default_filter = filter.ChangeFilter (project = "octave", branch = "default")

octave_stable_filter = filter.ChangeFilter (project = "stable octave", branch = "stable")

mxe_octave_default_filter = filter.ChangeFilter (project = "mxe-octave", branch = "default")

## SCHEDULERS

## Configure the Schedulers, which decide how to react to incoming
## changes.

from buildbot.schedulers.basic import SingleBranchScheduler
from buildbot.schedulers.forcesched import ForceScheduler
from buildbot.schedulers import timed

all_default_octave_builders = [];
#all_default_octave_builders.append ("gcc-4.9-debian")
#all_default_octave_builders.append ("gcc-5-debian")
all_default_octave_builders.append ("gcc-6-debian") # mtmx
all_default_octave_builders.append ("gcc-7-debian") # jwe
all_default_octave_builders.append ("gcc-7-lto-debian") # jwe
all_default_octave_builders.append ("gcc-fedora") # das
all_default_octave_builders.append ("gcc-lto-fedora") # das
all_default_octave_builders.append ("no-extras-debian") # jwe
all_default_octave_builders.append ("clang-3.9-debian") # mtmx
all_default_octave_builders.append ("clang-4.0-debian") # jwe
all_default_octave_builders.append ("clang-5.0-debian") # jwe
all_default_octave_builders.append ("clang-fedora") # das
all_default_octave_builders.append ("clang-osx") # simone

all_stable_octave_builders = [];
all_stable_octave_builders.append ("stable-gcc-7-debian") # jwe
all_stable_octave_builders.append ("stable-gcc-7-lto-debian") # jwe
all_stable_octave_builders.append ("stable-gcc-fedora") # das
all_stable_octave_builders.append ("stable-no-extras-debian") # jwe
all_stable_octave_builders.append ("stable-clang-4.0-debian") # jwe
all_stable_octave_builders.append ("stable-clang-5.0-debian") # jwe
all_stable_octave_builders.append ("stable-clang-osx") # simone

all_mxe_octave_builders = [];
all_mxe_octave_builders.append ("w32-on-debian") # jwe
all_mxe_octave_builders.append ("w64-32-on-debian") # jwe
all_mxe_octave_builders.append ("w64-64-on-debian") # jwe
all_mxe_octave_builders.append ("w32-stable-on-debian") # jwe
all_mxe_octave_builders.append ("w64-32-stable-on-debian") # jwe
all_mxe_octave_builders.append ("mxe-native-on-debian") # jwe
all_mxe_octave_builders.append ("mxe-native-all-on-debian") # jwe

c["schedulers"] = []

c["schedulers"].append (SingleBranchScheduler (name = "default octave",
                                               change_filter = octave_default_filter,
                                               treeStableTimer = 5*60,
                                               builderNames = all_default_octave_builders))

c["schedulers"].append (ForceScheduler (name = "force_default_octave", builderNames = all_default_octave_builders))

c["schedulers"].append (SingleBranchScheduler (name = "stable octave",
                                               change_filter = octave_stable_filter,
                                               treeStableTimer = 5*60,
                                               builderNames = all_stable_octave_builders))

c["schedulers"].append (ForceScheduler (name = "force_stable_octave", builderNames = all_stable_octave_builders))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-w32",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["w32-on-debian"],
                                       hour = 0))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-w64-32",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["w64-32-on-debian"],
                                       hour = 6))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-w64-64",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["w64-64-on-debian"],
                                       hour = 12))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-native",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["mxe-native-on-debian"],
                                       hour = 18))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-native-all",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["mxe-native-all-on-debian"],
                                       hour = 0))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-w32-stable",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["w32-stable-on-debian"],
                                       hour = 8))

## Here, branch is the mxe-octave branch.
c["schedulers"].append (timed.Nightly (name = "periodic mxe-octave-w64-32-stable",
                                       branch = "default",
                                       change_filter = mxe_octave_default_filter,
                                       builderNames = ["w64-32-stable-on-debian"],
                                       hour = 16))

c["schedulers"].append (ForceScheduler (name = "force_mxe_octave", builderNames = all_mxe_octave_builders))

## BUILDERS

## The 'builders' list defines the Builders, which tell Buildbot how
## to perform a build:  what steps, and which workers can execute them.
## Note that any particular build will only take place on one worker.

from buildbot.process.factory import BuildFactory
from buildbot.steps.source.mercurial import Mercurial
from buildbot.steps.shell import ShellCommand
from buildbot.steps.shell import Configure
from buildbot.steps.shell import Compile
from buildbot.steps.shell import Test

## Steps we may use in more than one build factory.

def build_cmd_list (cmd, nice = 0, opts = []):
  cmd_list = []

  if nice != 0:
    cmd_list.extend (["nice", "-n", str (nice)])

  if isinstance (cmd, list):
    cmd_list.extend (cmd)
  else:
    cmd_list.append (cmd)

  if isinstance (opts, list):
    cmd_list.extend (opts)
  else:
    cmd_list.append (opts)

  return cmd_list


build_env = { "PATH" : "${HOME}/bin:${PATH}" };

def mk_octave_hg_update_step (repo, branch):
  return Mercurial (repourl = repo,
                    defaultBranch = branch, branchType = "inrepo",
                    workdir = "src", mode = "full", method = "fresh",
                    haltOnFailure = True)

def mk_octave_bootstrap_step (nice = 0):
  boot_cmd = build_cmd_list ("./bootstrap", nice = nice)
  return ShellCommand (command = boot_cmd, workdir = "src", env = build_env,
                       description = "bootstrap")

sh_rm_build_dir = ShellCommand (command = ["rm", "-rf", "build"], workdir = ".",
                                env = build_env, description = "clean build dir")

sh_mk_build_dir = ShellCommand (command = ["mkdir", "build"],
                                description = "create build dir")

def mk_octave_configure_step (nice = 0, opts = []):
  conf_cmd = build_cmd_list ("../src/configure", nice = nice, opts = opts)
  return Configure (command = conf_cmd, workdir = "build", env = build_env)


def mk_octave_compile_step (nice = 0, opts = []):
  make_cmd = build_cmd_list (["make", "V=1"], nice = nice, opts = opts)
  return Compile (command = make_cmd, workdir = "build", env = build_env,
                  warningPattern = ":[0-9][0-9]*:[0-9][0-9]*:warning: ")

import re
from buildbot.process import logobserver
from buildbot.process.results import SUCCESS
from buildbot.process.results import FAILURE
from buildbot.process.results import WARNINGS

class octave_test_observer (logobserver.LogLineObserver):

  def __init__ (self, warningPattern):
    logobserver.LogLineObserver.__init__ (self)
    if warningPattern:
      self.warningPattern = re.compile (warningPattern)
    else:
      self.warningPattern = None
    self.rc = SUCCESS
    self.total = 0
    self.failed = 0
    self.warnings = 0
    self.complete = False

  testsRe = re.compile (r"^  (PASS|FAIL|REGRESSION|XFAIL|SKIP).*(\d+)")
        
  def outLineReceived (self, line):
    if self.warningPattern.match (line):
      self.warnings += 1
    mo = self.testsRe.search (line)
    if mo:
      type = mo.group(1)
      count = int (mo.group(2))
      self.total += num
      if type == "FAIL" or type == "REGRESSION":
        if count > 0:
          self.rc = FAILURE
        self.failed += count


class octave_test (Test):

  def __init__ (self, *args, **kwargs):
    Test.__init__ (self, *args, **kwargs)
    self.observer = octave_test_observer (warningPattern = self.warningPattern)
    self.addLogObserver ('stdio', self.observer)

  def evaluateCommand (self, cmd):
    if self.observer.total:
      passed = self.observer.total - self.observer.failed

      self.setTestResults (total = self.observer.total,
                           failed = self.observer.failed,
                           passed = passed,
                           warnings = self.observer.warnings)

    rc = self.observer.rc
    if rc == SUCCESS and self.observer.warnings:
      rc = WARNINGS
    return rc


def mk_octave_test_step (nice = 0, xvfb = True):
  if xvfb:
    cmd = ["xvfb-run", "-a", "-s", "-screen 0 640x480x24"]
  else:
    cmd = []
  cmd.extend (["make", "V=1", "check"])
  test_cmd = build_cmd_list (cmd, nice = nice)
  return octave_test (command = test_cmd, workdir = "build", env = build_env)


def mk_octave_factory (nice, configure_opts, compile_opts, branch, xvfb = True):
  factory = BuildFactory ()

  factory.addStep (mk_octave_hg_update_step (octave_hg_repo, branch))
  factory.addStep (mk_octave_bootstrap_step (nice = nice))
  factory.addStep (sh_rm_build_dir)
  factory.addStep (sh_mk_build_dir)
  factory.addStep (mk_octave_configure_step (nice = nice, opts = configure_opts))
  factory.addStep (mk_octave_compile_step (nice = nice, opts = compile_opts))
  factory.addStep (mk_octave_test_step (nice = nice, xvfb = xvfb))

  return factory


def mk_gcc_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice, [], compile_opts, branch)


def mk_gcc_4_9_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=gcc-4.9", "CXX=g++-4.9", "F77=gfortran-4.9", "--without-magick"],
                            compile_opts, branch)


## Default build.
def mk_gcc_5_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=gcc-5", "CXX=g++-5", "F77=gfortran-5"],
                            compile_opts, branch)


def mk_gcc_6_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=gcc-6", "CXX=g++-6", "F77=gfortran-6"],
                            compile_opts, branch)
                                   

def mk_gcc_7_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=gcc-7", "CXX=g++-7", "F77=gfortran-7"],
                            compile_opts, branch)
                                   

def mk_gcc_7_lto_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=gcc-7", "CXX=g++-7", "F77=gfortran-7",
                             "CFLAGS=-O2 -flto=4 -ffat-lto-objects",
                             "CXXFLAGS=-O2 -flto=4 -ffat-lto-objects",
                             "FFLAGS=-O2 -flto=4 -ffat-lto-objects",
                             "LDFLAGS=-flto=4",
                             "NM=gcc-nm-7", "AR=gcc-ar-7", "RANLIB=gcc-ranlib-7"],
                            compile_opts, branch)
                                   

def mk_gcc_lto_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CFLAGS=-O2 -flto=4 -ffat-lto-objects",
                             "CXXFLAGS=-O2 -flto=4 -ffat-lto-objects",
                             "FFLAGS=-O2 -flto=4 -ffat-lto-objects",
                             "LDFLAGS=-flto=4",
                             "NM=gcc-nm", "AR=gcc-ar", "RANLIB=gcc-ranlib"],
                            compile_opts, branch)
                                   

no_extras = ["--disable-docs",
             "--disable-fftw-threads",
             "--disable-java",
             "--disable-jit",
             "--disable-openmp",
             "--disable-readline",
             "--without-osmesa",
             "--without-amd",
             "--without-arpack",
             "--without-bz2",
             "--without-camd",
             "--without-ccolamd",
             "--without-cholmod",
             "--without-colamd",
             "--without-curl",
             "--without-cxsparse",
             "--without-fftw3",
             "--without-fftw3f",
             "--without-fltk",
             "--without-framework-opengl",
             "--without-glpk",
             "--without-hdf5",
             "--without-klu",
             "--without-sundials-ida",
             "--without-sundials_nvecserial",
             "--without-magick",
             "--without-opengl",
             "--without-openssl",
             "--without-portaudio",
             "--without-qhull",
             "--without-qrupdate",
             "--without-qscintilla",
             "--without-qt",
             "--without-sndfile",
             "--without-sundials_ida",
             "--without-sundials_nvecserial",
             "--without-umfpack",
             "--without-x",
             "--without-z"]

def mk_no_extras_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice, no_extras, compile_opts, branch)


def mk_clang_3_8_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=clang-3.8", "CXX=clang++-3.8"],
                            compile_opts, branch)


def mk_clang_3_9_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=clang-3.9", "CXX=clang++-3.9"],
                            compile_opts, branch)

def mk_clang_4_0_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=clang-4.0", "CXX=clang++-4.0"],
                            compile_opts, branch)

def mk_clang_5_0_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=clang-5.0", "CXX=clang++-5.0"],
                            compile_opts, branch)

def mk_clang_factory (nice, compile_opts, branch):
  return mk_octave_factory (nice,
                            ["CC=clang", "CXX=clang++"],
                            compile_opts, branch)

def mk_clang_osx_factory (nice, compile_opts, branch):
  ## The linker does search /usr/local/lib, but it does so after
  ## searching /usr/lib.  That selects a readline library that is not
  ## fully compatible with GNU readline.
  return mk_octave_factory (nice,
                            ["CC=clang",
                             "CXX=clang++",
                             "CPPFLAGS=-I/opt/X11/include -I/usr/local/opt/gettext/include -I/usr/local/opt/icu4c/include -I/usr/local/opt/openssl/include -I/usr/local/opt/readline/include -I/usr/local/opt/sqlite/include",
                             "LDFLAGS=-L/usr/local/lib -L/opt/X11/lib -L/usr/local/opt/qt/lib -L/usr/local/opt/readline/lib -L/usr/local/opt/texinfo/lib -L/usr/local/opt/bison/lib -L/usr/local/opt/gettext/lib -L/usr/local/opt/icu4c/lib -L/usr/local/opt/libffi/lib -L/usr/local/opt/openblas/lib -L/usr/local/opt/openssl/lib -L/usr/local/opt/sqlite/lib",
                             "PKG_CONFIG_PATH=/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/qt/lib/pkgconfig",
                             "--enable-link-all-dependencies",
                             "--with-x=no",
                             "--without-osmesa",
                             "--with-blas=openblas"],
                            compile_opts, branch, xvfb = False)

from buildbot.config import BuilderConfig

c["builders"] = []

#c["builders"].append (BuilderConfig (name = "gcc-4.9-debian",
#                                     workernames = ["jwe-debian-x86_64-0"],
#                                     factory = mk_gcc_4_9_factory (19, "-j8", "default")))

#c["builders"].append (BuilderConfig (name = "gcc-5-debian",
#                                     workernames = ["jwe-debian-x86_64-0"],
#                                     factory = mk_gcc_5_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "gcc-6-debian",
                                     workernames = ["mtmx-debian-x86_64"],
                                     factory = mk_gcc_6_factory (10, "-j2", "default")))

c["builders"].append (BuilderConfig (name = "gcc-7-debian",
                                     workernames = ["jwe-debian-x86_64-1"],
                                     factory = mk_gcc_7_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "stable-gcc-7-debian",
                                     workernames = ["jwe-debian-x86_64-1"],
                                     factory = mk_gcc_7_factory (19, "-j8", "stable")))

c["builders"].append (BuilderConfig (name = "gcc-7-lto-debian",
                                     workernames = ["jwe-debian-x86_64-2"],
                                     factory = mk_gcc_7_lto_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "stable-gcc-7-lto-debian",
                                     workernames = ["jwe-debian-x86_64-2"],
                                     factory = mk_gcc_7_lto_factory (19, "-j8", "stable")))

c["builders"].append (BuilderConfig (name = "gcc-fedora",
                                     workernames = ["das_fc25-x86_64"],
                                     factory = mk_gcc_factory (0, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "stable-gcc-fedora",
                                     workernames = ["das_fc25-x86_64"],
                                     factory = mk_gcc_factory (0, "-j8", "stable")))

c["builders"].append (BuilderConfig (name = "gcc-lto-fedora",
                                     workernames = ["das_fc25-x86_64"],
                                     factory = mk_gcc_lto_factory (10, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "no-extras-debian",
                                     workernames = ["jwe-debian-x86_64-1"],
                                     factory = mk_no_extras_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "stable-no-extras-debian",
                                     workernames = ["jwe-debian-x86_64-1"],
                                     factory = mk_no_extras_factory (19, "-j8", "stable")))

##c["builders"].append (BuilderConfig (name = "clang-3.8-debian",
##                                     workernames = ["jwe-debian-x86_64-2"],
##                                     factory = mk_clang_3_8_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "clang-3.9-debian",
                                     workernames = ["mtmx-debian-x86_64"],
                                     factory = mk_clang_3_9_factory (19, "-j2", "default")))

c["builders"].append (BuilderConfig (name = "clang-4.0-debian",
                                     workernames = ["jwe-debian-x86_64-0"],
                                     factory = mk_clang_4_0_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "stable-clang-4.0-debian",
                                     workernames = ["jwe-debian-x86_64-0"],
                                     factory = mk_clang_4_0_factory (19, "-j8", "stable")))

c["builders"].append (BuilderConfig (name = "clang-5.0-debian",
                                     workernames = ["jwe-debian-x86_64-2"],
                                     factory = mk_clang_5_0_factory (19, "-j8", "default")))

c["builders"].append (BuilderConfig (name = "stable-clang-5.0-debian",
                                     workernames = ["jwe-debian-x86_64-2"],
                                     factory = mk_clang_5_0_factory (19, "-j8", "stable")))

c["builders"].append (BuilderConfig (name = "clang-fedora",
                                     workernames = ["das_fc25-x86_64"],
                                     factory = mk_clang_factory (19, "-j8", "default")))


c["builders"].append (BuilderConfig (name = "clang-osx",
                                     workernames = ["epfl-elcapitan-x86_64"],
                                     factory = mk_clang_osx_factory (0, "-j4", "default")))

c["builders"].append (BuilderConfig (name = "stable-clang-osx",
                                     workernames = ["epfl-elcapitan-x86_64"],
                                     factory = mk_clang_osx_factory (0, "-j4", "stable")))


def mk_mxe_octave_hg_update_step (repo):
  return Mercurial (repourl = repo,
                    defaultBranch = "default", branchType = "inrepo",
                    workdir = "src", mode = "full", method = "fresh",
                    haltOnFailure = True)


def mk_mxe_octave_bootstrap_step (nice = 0):
  boot_cmd = build_cmd_list ("autoconf", nice = nice)
  return ShellCommand (command = boot_cmd, workdir = "src", env = build_env,
                       description = "bootstrap")


def mk_mxe_octave_configure_step (nice = 0, branch = "default", opts = []):
  conf_cmd = build_cmd_list (["./configure",
                              "--with-pkg-dir=../../mxe-pkg-src",
                              "--with-ccache", "--enable-octave=" + branch,
                              "--enable-binary-packages"],
                             nice = nice, opts = opts)
  return Configure (command = conf_cmd, workdir = "src", env = build_env)


def mk_mxe_octave_clean_step (nice = 0):
  boot_cmd = build_cmd_list (["make", "clean"], nice = nice)
  return ShellCommand (command = boot_cmd, workdir = "src", env = build_env,
                       description = "clean")


## Timeout is large for these steps because mxe-octave currently only
## prints a status update for each package, not detailed output from
## make.  The way the dependencies currently work, making
## hg-octave-dist will also cause all the build tools to be updated,
## and some of those make take significant time to build, especially
## if the build is running on a heavily loaded system and this step
## has a high nice value.

def mk_mxe_octave_hg_tarball_step (nice = 0, jobs = 8, branch = "default"):
  make_cmd = build_cmd_list (["make", "JOBS=" + str (jobs), "hg-octave-dist", "hg-octave-branch=" + branch],
                             nice = nice)
  return Compile (command = make_cmd, workdir = "src", env = build_env,
                  timeout = 14400)


def mk_mxe_octave_compile_step (nice = 0, jobs = 8, opts = []):
  make_cmd = build_cmd_list (["make", "JOBS=" + str (jobs)],
                             nice = nice, opts = opts)
  return Compile (command = make_cmd, workdir = "src", env = build_env,
                  timeout = 14400)


def mk_mxe_octave_factory (nice, jobs, branch, configure_opts, compile_opts):
  factory = BuildFactory ()

  factory.addStep (mk_mxe_octave_hg_update_step (mxe_octave_hg_repo))
  factory.addStep (mk_mxe_octave_bootstrap_step (nice = nice))
  ## Must run configure to ensure clean target will work, then must
  ## run configure again to recreate makefile.
  factory.addStep (mk_mxe_octave_configure_step (nice = nice, branch = branch,
                                                 opts = configure_opts))
  factory.addStep (mk_mxe_octave_clean_step (nice = nice))
  factory.addStep (mk_mxe_octave_configure_step (nice = nice, branch = branch,
                                                 opts = configure_opts))
  ## Create a tarball file from an hg checkout, then build from that.
  ## This also builds all dependencies for Octave, so it can take a
  ## while.  Using ccache should help us significantly since we are
  ## typically rebuilding the same sets of packages repeatedly.
  factory.addStep (mk_mxe_octave_hg_tarball_step (nice = nice, jobs = jobs,
                                                  branch = branch))
  factory.addStep (mk_mxe_octave_compile_step (nice = nice, jobs = jobs,
                                               opts = compile_opts))
  ## factory.addStep (mk_mxe_octave_test_step (nice = nice))

  return factory


def mk_w32_factory (nice, jobs, branch, compile_opts):
  return mk_mxe_octave_factory (nice, jobs, branch,
                                ["--enable-qt5",
                                 "--enable-devel-tools",
                                 "--disable-windows-64",
                                 "--disable-system-opengl"],
                                compile_opts)


def mk_w64_32_factory (nice, jobs, branch, compile_opts):
  configure_opts = ["--enable-qt5",
                    "--enable-devel-tools",
                    "--disable-system-opengl"]
  if branch == "stable":
    configure_opts.extend (["--disable-64"])

  return mk_mxe_octave_factory (nice, jobs, branch,
                                configure_opts,
                                compile_opts)


def mk_w64_64_factory (nice, jobs, branch, compile_opts):
  return mk_mxe_octave_factory (nice, jobs, branch,
                                ["--enable-qt5",
                                 "--enable-devel-tools",
                                 "--enable-fortran-int64",
                                 "--disable-system-opengl",
                                 "--enable-64"],
                                compile_opts)


def mk_native_factory (nice, jobs, branch, compile_opts):
  return mk_mxe_octave_factory (nice, jobs, branch,
                                ["--enable-native-build",
                                 "--enable-qt5",
                                 "--enable-lib64-directory",
                                 "--enable-pic-flag",
                                 "--disable-devel-tools",
                                 "--enable-system-x11-libs",
                                 "--enable-system-fontconfig",
                                 "--enable-system-gcc",
                                 "gnu-linux"],
                                compile_opts)


def mk_native_all_factory (nice, jobs, branch, compile_opts):
  return mk_mxe_octave_factory (nice, jobs, branch,
                                ["--enable-native-build",
                                 "--enable-qt5",
                                 "--enable-lib64-directory",
                                 "--enable-pic-flag",
                                 "--disable-devel-tools",
                                 "--disable-system-x11-libs",
                                 "--disable-system-fontconfig",
                                 "--disable-system-gcc",
                                 "--disable-system-opengl",
                                 "gnu-linux"],
                                compile_opts)


c["builders"].append (BuilderConfig (name = "w32-on-debian",
                                     workernames = ["jwe-debian-x86_64-0"],
                                     factory = mk_w32_factory (19, 8, "default", "nsis-installer")))

c["builders"].append (BuilderConfig (name = "w64-32-on-debian",
                                     workernames = ["jwe-debian-x86_64-0"],
                                     factory = mk_w64_32_factory (19, 8, "default", "nsis-installer")))

c["builders"].append (BuilderConfig (name = "w64-64-on-debian",
                                     workernames = ["jwe-debian-x86_64-0"],
                                     factory = mk_w64_64_factory (19, 8, "default", "nsis-installer")))


c["builders"].append (BuilderConfig (name = "mxe-native-on-debian",
                                     workernames = ["jwe-debian-x86_64-0"],
                                     factory = mk_native_factory (19, 8, "default", "tar-dist")))

c["builders"].append (BuilderConfig (name = "mxe-native-all-on-debian",
                                     workernames = ["jwe-debian-x86_64-3"],
                                     factory = mk_native_all_factory (19, 8, "default", "tar-dist")))


c["builders"].append (BuilderConfig (name = "w32-stable-on-debian",
                                     workernames = ["jwe-debian-x86_64-3"],
                                     factory = mk_w32_factory (19, 8, "stable", "nsis-installer")))

c["builders"].append (BuilderConfig (name = "w64-32-stable-on-debian",
                                     workernames = ["jwe-debian-x86_64-3"],
                                     factory = mk_w64_32_factory (19, 8, "stable", "nsis-installer")))

## PROJECT IDENTITY

## the 'title' string will appear at the top of this buildbot
## installation's html.WebStatus home page (linked to the 'titleURL')
## and is embedded in the title of the waterfall HTML page.

c["title"] = "GNU Octave Buildbot"
c["titleURL"] = "https://octave.org"

# The 'buildbotURL' string should point to the location where the buildbot's
# internal web server is visible. This typically uses the port number set in
# the 'www' entry below, but with an externally-visible host name which the
# buildbot cannot figure out without some help.

c['buildbotURL'] = "http://buildbot.octave.org:8011/"

## Minimalistic config to activate new web UI

from buildbot.plugins import util

c['www'] = {
  "port" : 8011,
  "auth" : util.UserPasswordAuth ({"octave" : "8avete$t$"}),
  "plugins" : { "waterfall_view" : True }
}

## DB URL

## This specifies what database buildbot uses to store its state.  You
## can leave this at its default for all but the largest installations.

c["db"] = { "db_url" : "sqlite:///state.sqlite" }

## NOTIFICATIONS

from buildbot.plugins import reporters

c["services"] = []

m = reporters.MailNotifier (fromaddr = "NO-REPLY@octave.org",
                            sendToInterestedUsers = False,
                            extraRecipients = ["octave-buildbot@gnu.org"],
                            mode = "failing")
c["services"].append (m)