#! /usr/bin/env python
# Copyright (c) 2005-2007 The Regents of The University of Michigan
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met: redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer;
# redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution;
# neither the name of the copyright holders nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# Authors: Steve Reinhardt

import sys
import os
import optparse
import datetime
from subprocess import call

progname = os.path.basename(sys.argv[0])

optparser = optparse.OptionParser()
add_option = optparser.add_option
add_option('-v', '--verbose', action='store_true', default=False,
           help='echo commands before executing')
add_option('--builds',
           default='ALPHA_SE,ALPHA_SE_MOESI_hammer,' \
           'ALPHA_SE_MESI_CMP_directory,'  \
           'ALPHA_SE_MOESI_CMP_directory,' \
           'ALPHA_SE_MOESI_CMP_token,' \
           'ALPHA_FS,' \
           'MIPS_SE,' \
           'POWER_SE,' \
           'SPARC_SE,SPARC_FS,' \
           'X86_SE,X86_FS,' \
           'ARM_SE,ARM_FS',
           help="comma-separated build targets to test (default: '%default')")
add_option('--test-variants', default='opt',
           help="comma-separated build variants to test (default: '%default')"\
           ", set to '' for none")
add_option('--compile-variants', default='debug,fast',
           help="comma-separated build variants to compile only (not test) " \
           "(default: '%default'), set to '' for none", metavar='VARIANTS')
add_option('--scons-opts', default='', metavar='OPTS',
           help='scons options')
add_option('-j', '--jobs', type='int', default=1, metavar='N',
           help='number of parallel jobs to use (0 to use all cores)')
add_option('-k', '--keep-going', action='store_true',
           help='keep going after errors')
add_option('--update-ref', action='store_true',
           help='update reference outputs')
add_option('-D', '--build-dir', default='', metavar='DIR',
           help='build directory location')
add_option('-n', "--no-exec", default=False, action='store_true',
           help="don't actually invoke scons, just echo SCons command line")

(options, tests) = optparser.parse_args()


# split a comma-separated list, but return an empty list if given the
# empty string
def split_if_nonempty(s):
    if not s:
        return []
    return s.split(',')

# split list options on ',' to get Python lists
builds = split_if_nonempty(options.builds)
test_variants = split_if_nonempty(options.test_variants)
compile_variants = split_if_nonempty(options.compile_variants)

options.build_dir = os.path.join(options.build_dir, 'build')

# Call os.system() and raise exception if return status is non-zero
def system(cmd):
    try:
        retcode = call(cmd, shell=True)
        if retcode < 0:
            print >>sys.stderr, "Child was terminated by signal", -retcode
            print >>sys.stderr, "When attemping to execute: %s" % cmd
            sys.exit(1)
        elif retcode > 0:
            print >>sys.stderr, "Child returned", retcode
            print >>sys.stderr, "When attemping to execute: %s" % cmd
            sys.exit(1)
    except OSError, e:
        print >>sys.stderr, "Execution failed:", e
        print >>sys.stderr, "When attemping to execute: %s" % cmd
        sys.exit(1)

targets = []

# start with compile-only targets, if any
if compile_variants:
    targets += ['%s/%s/m5.%s' % (options.build_dir, build, variant)
                for variant in compile_variants
                for build in builds]

# By default run the 'quick' tests
if not tests:
    tests = ['quick']

# set up test targets for scons
if 'all' in tests:
    targets += ['%s/%s/tests/%s' % (options.build_dir, build, variant)
                for build in builds
                for variant in test_variants]
else:
    # Ugly! Since we don't have any quick SPARC_FS tests remove the
    # SPARC_FS target If we ever get a quick SPARC_FS test, this code
    # should be removed
    if 'quick' in tests and 'SPARC_FS' in builds:
        builds.remove('SPARC_FS')
    targets += ['%s/%s/tests/%s/%s' % (options.build_dir, build, variant, test)
                for build in builds
                for variant in test_variants
                for test in tests]

def cpu_count():
    if 'bsd' in sys.platform or sys.platform == 'darwin':
        try:
            return int(os.popen('sysctl -n hw.ncpu').read())
        except ValueError:
            pass
    else:
        try:
            return os.sysconf('SC_NPROCESSORS_ONLN')
        except (ValueError, OSError, AttributeError):
            pass

    raise NotImplementedError('cannot determine number of cpus')

scons_opts = options.scons_opts
if options.jobs != 1:
    if options.jobs == 0:
        options.jobs = cpu_count()
    scons_opts += ' -j %d' % options.jobs
if options.keep_going:
    scons_opts += ' -k'
if options.update_ref:
    scons_opts += ' --update-ref'

cmd = 'scons --ignore-style %s %s' % (scons_opts, ' '.join(targets))
if options.no_exec:
    print cmd
else:
    system(cmd)
    sys.exit(0)
