示例#1
0
def main():
    # find the path to the actual autobuild exectuable and ensure it's in PATH
    # so that build commands can find it and other scripts distributed with autobuild.
    script_path = os.path.dirname(common.get_autobuild_executable_path())

    logger = logging.getLogger('autobuild')
    try:
        # Dedup the path after appending script_path in case it's already
        # present in the PATH string.
        os.environ['PATH'] = common.dedup_path(
            os.pathsep.join((os.environ.get('PATH'), script_path)))
        sys.exit(Autobuild().main(sys.argv[1:]))
    except KeyboardInterrupt as e:
        sys.exit("Aborted...")
    except common.AutobuildError as e:
        if logger.getEffectiveLevel() <= logging.DEBUG:
            logger.exception(str(e))
        msg = ["ERROR: ", str(e)]
        if logger.getEffectiveLevel() > logging.DEBUG:
            msg.append(
                "\nFor more information: try re-running your command with")
            if logger.getEffectiveLevel() > logging.INFO:
                msg.append(" --verbose or")
            msg.append(" --debug")
        sys.exit(''.join(msg))
def do_source_environment(args):
    var_mapping = {
            'AUTOBUILD_EXECUTABLE_PATH':common.get_autobuild_executable_path(),
            'AUTOBUILD_VERSION_STRING':common.AUTOBUILD_VERSION_STRING,
            'AUTOBUILD_PLATFORM':common.get_current_platform(),
            'MAKEFLAGS':"",
            'DISTCC_HOSTS':"",
        }

    if common.get_current_platform() is "windows":
        try:
            # reset stdout in binary mode so sh doesn't get confused by '\r'
            import msvcrt
            msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
        except ImportError:
            # cygwin gets a pass
            pass

        # load vsvars32.bat variables
        # *TODO - find a way to configure this instead of hardcoding to vc80
        try:
            vs_ver = os.environ['AUTOBUILD_VSVER']
        except KeyError:
            vs_ver = "80"
            
        var_mapping.update(load_vsvars(vs_ver))
        var_mapping.update(AUTOBUILD_EXECUTABLE_PATH=("$(cygpath -u '%s')" % common.get_autobuild_executable_path()))

        try:
            use_ib = int(os.environ['USE_INCREDIBUILD'])
        except ValueError:
            logger.warning("USE_INCREDIBUILD environment variable contained garbage %r (expected 0 or 1), turning incredibuild off" % os.environ['USE_INCREDIBUILD'])
            use_ib = 0
        except KeyError:
            use_ib = int(bool(common.find_executable('BuildConsole')))

        var_mapping.update(USE_INCREDIBUILD=use_ib)

    sys.stdout.write(environment_template % var_mapping)

    if get_params:
        # *TODO - run get_params.generate_bash_script()
        pass
def main():
    # find the path to the actual autobuild exectuable and ensure it's in PATH
    # so that build commands can find it and other scripts distributed with autobuild.
    script_path = os.path.dirname(common.get_autobuild_executable_path())

    logger = logging.getLogger('autobuild')
    try:
        os.environ['PATH'] = os.environ.get('PATH') + os.pathsep + script_path
        sys.exit( Autobuild().main(sys.argv[1:]) )
    except KeyboardInterrupt, e:
        sys.exit("Aborted...")
def internal_source_environment(configurations, varsfile):
    """
    configurations is a list of requested configurations (e.g. 'Release'). If
    the list isn't empty, the first entry will be used; any additional entries
    will be ignored with a warning.

    varsfile, if not None, is the name of a local variables file as in
    https://bitbucket.org/lindenlab/build-variables/src/tip/variables.

    os.environ['AUTOBUILD_VSVER'] indirectly indicates a Visual Studio
    vcvarsall.bat script from which to load variables. Its values are e.g.
    '100' for Visual Studio 2010 (VS 10), '120' for Visual Studio 2013 (VS 12)
    and so on. A correct value nnn for the running system will identify a
    corresponding VSnnnCOMNTOOLS environment variable.

    Returns a triple of dicts (exports, vars, vsvars):

    exports is intended to propagate down to child processes, hence should be
    exported by the consuming bash shell.

    vars is intended for use by the consuming bash shell, hence need not be
    exported.

    vsvars contains variables set by the relevant Visual Studio vcvarsall.bat
    script. It is an empty dict on any platform but Windows.
    """
    if not common.is_system_windows():
        vsver = None  # N/A
    else:
        try:
            vsver = os.environ['AUTOBUILD_VSVER']
        except KeyError:
            # try to figure out most recent Visual Studio version
            try:
                vsver = _available_vsvers()[-1]
            except IndexError:
                logger.warning(
                    "No Visual Studio install detected -- "
                    "certain configuration variables will not be available")
                vsver = None

    # OPEN-259: it turns out to be important that if AUTOBUILD is already set
    # in the environment, we should LEAVE IT ALONE. So if it exists, use the
    # existing value. Otherwise just use our own executable path.
    autobuild_path = common.get_autobuild_executable_path()
    AUTOBUILD = os.environ.get("AUTOBUILD", autobuild_path)
    # The cross-platform environment_template contains a generic 'vars' slot
    # where we can insert lines defining environment variables. Putting a
    # variable definition into this 'exports' dict causes it to be listed
    # there with an 'export' statement; putting a variable definition into the
    # 'vars' dict lists it there as local to that bash process. Logic just
    # before expanding environment_template populates 'exports' and 'vars'
    # into var_mapping["vars"]. We defer it that long so that conditional
    # logic below can, if desired, add to either 'exports' or 'vars' first.
    exports = dict(
        AUTOBUILD=AUTOBUILD,
        AUTOBUILD_VERSION_STRING=common.AUTOBUILD_VERSION_STRING,
        AUTOBUILD_PLATFORM=common.get_current_platform(),
    )
    vars = dict(
        ##      MAKEFLAGS="",
        ##      DISTCC_HOSTS="",
    )
    vsvars = {}

    # varsfile could have been set either of two ways above, check again
    if varsfile is not None:
        # Read variable definitions from varsfile. Syntax restrictions are
        # documented in the build-variables/variables file itself, but
        # essentially it's the common subset of bash and string.Template
        # expansion functionality.
        # This is what we expect every substantive line in the input file to
        # look like: a valid variable name (starting with letter or
        # underscore, containing only letters, underscores or digits) = a
        # double-quoted value. We do not presently tolerate extra whitespace.
        assign_line = re.compile(r'^([A-Za-z_][A-Za-z0-9_]+)="(.*)"$')
        vfvars = {}
        try:
            with open(varsfile) as vf:
                for linen0, line in enumerate(vf):
                    # skip empty lines and comment lines
                    if line == '\n' or line.startswith('#'):
                        continue
                    match = assign_line.match(line.rstrip())
                    if not match:
                        # Fatal error is the only sure way to get a developer
                        # to fix a bad assignment in the variables file. If we
                        # just skip it with a warning, it could be weeks
                        # before we figure out why some large subset of
                        # third-party packages was built without essential
                        # compiler switches.
                        raise SourceEnvError(
                            "%s(%s): malformed variable assignment:\n%s" %
                            (varsfile, linen0 + 1, line.rstrip()))
                    var, value = match.group(1, 2)
                    try:
                        # Rely on the similarity between string.Template
                        # subtitution syntax and bash substitution syntax.
                        vfvars[var] = string.Template(value).substitute(vfvars)
                    except ValueError as err:
                        raise SourceEnvError(
                            "%s(%s): bad substitution syntax: %s\n%s" %
                            (varsfile, linen0 + 1, err, line.rstrip()))
                    except KeyError as err:
                        raise SourceEnvError(
                            "%s(%s): undefined variable %s:\n%s" %
                            (varsfile, linen0 + 1, err, line.rstrip()))
        except (IOError, OSError) as err:
            # Even though it's only a warning to fail to specify varsfile,
            # it's a fatal error to specify one that doesn't exist or can't be
            # read.
            raise SourceEnvError("%s: can't read '%s': %s" %
                                 (err.__class__.__name__, varsfile, err))

        # Here vfvars contains all the variables set in varsfile. Before
        # passing them along to the 'vars' dict, make a convenience pass over
        # them to extract simpler variable names specific to the platform and
        # build type.

        # If we recognize the current platform, provide shorthand vars for it.
        try:
            # Base this on sys.platform rather than
            # common.get_current_platform() because we don't want to have to
            # enumerate common.PLATFORM_WINDOWS, common.PLATFORM_WINDOWS64,
            # etc. just to blur the distinction between them again.
            platform = dict(
                win32="WINDOWS",
                cygwin="WINDOWS",
                darwin="DARWIN",
                linux2="LINUX",
            )[sys.platform]
        except KeyError:
            logger.warning("Unsupported platform %s: no short names provided" %
                           sys.platform)
        else:
            platform_re = re.compile(r'(.*_BUILD)_%s(.*)$' % platform)
            # use items() rather than iteritems(): we're modifying as we iterate
            for var, value in vfvars.items():
                match = platform_re.match(var)
                if match:
                    # add a shorthand variable that excludes _PLATFORM
                    vfvars[''.join(match.group(1, 2))] = value

        # If caller specified configuration, provide shorthand vars for it.
        # If nothing was specified, configurations will be empty; if something
        # was, take only the first specified configuration.
        if configurations:
            configuration = configurations[0].upper()
            if configurations[1:]:
                logger.warning("Ignoring extra configurations %s" %
                               ", ".join(configurations[1:]))
            configuration_re = re.compile(r'(.*_BUILD)_%s(.*)$' %
                                          configuration)
            # use items() because we're modifying as we iterate
            for var, value in vfvars.items():
                match = configuration_re.match(var)
                if match:
                    # add a shorthand variable that excludes _CONFIGURATION
                    vfvars[''.join(match.group(1, 2))] = value

        # We've been keeping varsfile variables separate so we can make the
        # above convenience passes through them without accidentally matching
        # pre-existing entries in 'vars'. Now dump everything into 'vars'.
        vars.update(vfvars)

    # Let KeyError, if any, propagate: lack of AUTOBUILD_ADDRSIZE would be
    # an autobuild coding error. So would any value for that variable
    # other than what's stated below.
    exports["AUTOBUILD_CONFIGURE_ARCH"] = {
        '32': 'i386',
        '64': 'x86_64',
    }[os.environ["AUTOBUILD_ADDRSIZE"]]

    if common.is_system_windows():
        try:
            use_ib = int(os.environ['USE_INCREDIBUILD'])
        except ValueError:
            logger.warning(
                "USE_INCREDIBUILD environment variable contained garbage %r "
                "(expected 0 or 1)" % os.environ['USE_INCREDIBUILD'])
            use_ib = 0
        except KeyError:
            # We no longer require Incredibuild for Windows builds. Therefore,
            # if you want to engage Incredibuild, you must explicitly set
            # USE_INCREDIBUILD=1. We no longer implicitly set that if
            # BuildConsole.exe is on the PATH.
            use_ib = 0

        vars["USE_INCREDIBUILD"] = str(use_ib)

        # Let KeyError, if any, propagate: lack of AUTOBUILD_ADDRSIZE would be
        # an autobuild coding error. So would any value for that variable
        # other than what's stated below.
        exports["AUTOBUILD_WIN_VSPLATFORM"] = {
            '32': 'Win32',
            '64': 'x64',
        }[os.environ["AUTOBUILD_ADDRSIZE"]]

        if vsver:
            # When one of our build-cmd.sh scripts invokes CMake on Windows, it's
            # probably prudent to use a -G switch for the specific Visual Studio
            # version we want to target. It's not that uncommon for a Windows
            # build host to have multiple VS versions installed, and it can
            # sometimes take a while for us to switch to the newest release. Yet
            # we do NOT want to hard-code the version-specific CMake generator
            # name into each 3p source repo: we know from experience that
            # sprinkling version specificity throughout a large collection of 3p
            # repos is part of what makes it so hard to upgrade the compiler. The
            # problem is that the mapping from vsver to (e.g.) "Visual Studio 12"
            # isn't necessarily straightforward -- we may have to maintain a
            # lookup dict. That dict should not be replicated into each 3p repo,
            # it should be central. It should be here.
            try:
                AUTOBUILD_WIN_CMAKE_GEN = {
                    '120': "Visual Studio 12",
                    '140': "Visual Studio 14",
                    '150': "Visual Studio 15",
                }[vsver]
            except KeyError:
                # We don't have a specific mapping for this value of vsver. Take
                # a wild guess. If we guess wrong, CMake will complain, and the
                # user will have to update autobuild -- which is no worse than
                # what s/he'd have to do anyway if we immediately produced an
                # error here. Plus this way, we defer the error until we hit a
                # build that actually consumes AUTOBUILD_WIN_CMAKE_GEN.
                AUTOBUILD_WIN_CMAKE_GEN = "Visual Studio %s" % (vsver[:-1])
            # Of course CMake also needs to know bit width :-P
            if os.environ["AUTOBUILD_ADDRSIZE"] == "64":
                AUTOBUILD_WIN_CMAKE_GEN += " Win64"
            exports["AUTOBUILD_WIN_CMAKE_GEN"] = AUTOBUILD_WIN_CMAKE_GEN

            # load vsvars32.bat variables
            vsvars = load_vsvars(vsver)

            # Resetting our PROMPT is a bit heavy-handed. Plus the substitution
            # syntax probably differs.
            vsvars.pop("PROMPT", None)

    return exports, vars, vsvars