def _node_errors(builder, env, tlist, slist):
    """Validate that the lists of target and source nodes are
    legal for this builder and environment.  Raise errors or
    issue warnings as appropriate.
    """

    # First, figure out if there are any errors in the way the targets
    # were specified.
    for t in tlist:
        if t.side_effect:
            raise UserError("Multiple ways to build the same target were specified for: %s" % t)
        if t.has_explicit_builder():
            # Check for errors when the environments are different
            # No error if environments are the same Environment instance
            if (not t.env is None and not t.env is env and
                    # Check OverrideEnvironment case - no error if wrapped Environments
                    # are the same instance, and overrides lists match
                    not (getattr(t.env, '__subject', 0) is getattr(env, '__subject', 1) and
                         getattr(t.env, 'overrides', 0) == getattr(env, 'overrides', 1) and
                         not builder.multi)):
                action = t.builder.action
                t_contents = t.builder.action.get_contents(tlist, slist, t.env)
                contents = builder.action.get_contents(tlist, slist, env)

                if t_contents == contents:
                    msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env))
                    SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg)
                else:
                    try:
                        msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (t,t_contents.decode('utf-8'),contents.decode('utf-8'))
                    except UnicodeDecodeError as e:
                        msg = "Two environments with different actions were specified for the same target: %s"%t
                    raise UserError(msg)
            if builder.multi:
                if t.builder != builder:
                    msg = "Two different builders (%s and %s) were specified for the same target: %s" % (t.builder.get_name(env), builder.get_name(env), t)
                    raise UserError(msg)
                # TODO(batch):  list constructed each time!
                if t.get_executor().get_all_targets() != tlist:
                    msg = "Two different target lists have a target in common: %s  (from %s and from %s)" % (t, list(map(str, t.get_executor().get_all_targets())), list(map(str, tlist)))
                    raise UserError(msg)
            elif t.sources != slist:
                msg = "Multiple ways to build the same target were specified for: %s  (from %s and from %s)" % (t, list(map(str, t.sources)), list(map(str, slist)))
                raise UserError(msg)

    if builder.single_source:
        if len(slist) > 1:
            raise UserError("More than one source given for single-source builder: targets=%s sources=%s" % (list(map(str,tlist)), list(map(str,slist))))
Validate that the lists of target and source nodes are
    legal for this builder and environment.  Raise errors or
    issue warnings as appropriate.