You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
87 lines
2.2 KiB
87 lines
2.2 KiB
// Copyright 2019 The Chromium OS Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
"syscall"
|
|
)
|
|
|
|
type userError struct {
|
|
err string
|
|
}
|
|
|
|
var _ error = userError{}
|
|
|
|
func (err userError) Error() string {
|
|
return err.err
|
|
}
|
|
|
|
func newUserErrorf(format string, v ...interface{}) userError {
|
|
return userError{err: fmt.Sprintf(format, v...)}
|
|
}
|
|
|
|
func newErrorwithSourceLocf(format string, v ...interface{}) error {
|
|
return newErrorwithSourceLocfInternal(2, format, v...)
|
|
}
|
|
|
|
func wrapErrorwithSourceLocf(err error, format string, v ...interface{}) error {
|
|
return newErrorwithSourceLocfInternal(2, "%s: %s", fmt.Sprintf(format, v...), err.Error())
|
|
}
|
|
|
|
func wrapSubprocessErrorWithSourceLoc(cmd *command, subprocessErr error) (exitCode int, err error) {
|
|
if subprocessErr == nil {
|
|
return 0, nil
|
|
}
|
|
if userErr, ok := getCCacheError(cmd, subprocessErr); ok {
|
|
return 0, userErr
|
|
}
|
|
if exitCode, ok := getExitCode(subprocessErr); ok {
|
|
return exitCode, nil
|
|
}
|
|
err = newErrorwithSourceLocfInternal(2, "failed to execute %#v: %s", cmd, subprocessErr)
|
|
return 0, err
|
|
}
|
|
|
|
// Based on the implementation of log.Output
|
|
func newErrorwithSourceLocfInternal(skip int, format string, v ...interface{}) error {
|
|
_, file, line, ok := runtime.Caller(skip)
|
|
if !ok {
|
|
file = "???"
|
|
line = 0
|
|
}
|
|
if lastSlash := strings.LastIndex(file, "/"); lastSlash >= 0 {
|
|
file = file[lastSlash+1:]
|
|
}
|
|
|
|
return fmt.Errorf("%s:%d: %s", file, line, fmt.Sprintf(format, v...))
|
|
}
|
|
|
|
func getExitCode(err error) (exitCode int, ok bool) {
|
|
if err == nil {
|
|
return 0, true
|
|
}
|
|
if exiterr, ok := err.(*exec.ExitError); ok {
|
|
if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
|
|
return status.ExitStatus(), true
|
|
}
|
|
}
|
|
return 0, false
|
|
}
|
|
|
|
func getCCacheError(compilerCmd *command, compilerCmdErr error) (ccacheErr userError, ok bool) {
|
|
if en, ok := compilerCmdErr.(syscall.Errno); ok && en == syscall.ENOENT &&
|
|
strings.Contains(compilerCmd.Path, "ccache") {
|
|
ccacheErr =
|
|
newUserErrorf("ccache not found under %s. Please install it",
|
|
compilerCmd.Path)
|
|
return ccacheErr, true
|
|
}
|
|
return ccacheErr, false
|
|
}
|