1 // Copyright 2017 Google Inc. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package build 16 17 import ( 18 "context" 19 "io" 20 "os" 21 "time" 22 23 "android/soong/ui/logger" 24 "android/soong/ui/tracer" 25 ) 26 27 type StdioInterface interface { 28 Stdin() io.Reader 29 Stdout() io.Writer 30 Stderr() io.Writer 31 } 32 33 type StdioImpl struct{} 34 35 func (StdioImpl) Stdin() io.Reader { return os.Stdin } 36 func (StdioImpl) Stdout() io.Writer { return os.Stdout } 37 func (StdioImpl) Stderr() io.Writer { return os.Stderr } 38 39 var _ StdioInterface = StdioImpl{} 40 41 type customStdio struct { 42 stdin io.Reader 43 stdout io.Writer 44 stderr io.Writer 45 } 46 47 func NewCustomStdio(stdin io.Reader, stdout, stderr io.Writer) StdioInterface { 48 return customStdio{stdin, stdout, stderr} 49 } 50 51 func (c customStdio) Stdin() io.Reader { return c.stdin } 52 func (c customStdio) Stdout() io.Writer { return c.stdout } 53 func (c customStdio) Stderr() io.Writer { return c.stderr } 54 55 var _ StdioInterface = customStdio{} 56 57 // Context combines a context.Context, logger.Logger, and StdIO redirection. 58 // These all are agnostic of the current build, and may be used for multiple 59 // builds, while the Config objects contain per-build information. 60 type Context struct{ *ContextImpl } 61 type ContextImpl struct { 62 context.Context 63 logger.Logger 64 65 StdioInterface 66 67 Thread tracer.Thread 68 Tracer tracer.Tracer 69 } 70 71 // BeginTrace starts a new Duration Event. 72 func (c ContextImpl) BeginTrace(name string) { 73 if c.Tracer != nil { 74 c.Tracer.Begin(name, c.Thread) 75 } 76 } 77 78 // EndTrace finishes the last Duration Event. 79 func (c ContextImpl) EndTrace() { 80 if c.Tracer != nil { 81 c.Tracer.End(c.Thread) 82 } 83 } 84 85 // CompleteTrace writes a trace with a beginning and end times. 86 func (c ContextImpl) CompleteTrace(name string, begin, end uint64) { 87 if c.Tracer != nil { 88 c.Tracer.Complete(name, c.Thread, begin, end) 89 } 90 } 91 92 // ImportNinjaLog imports a .ninja_log file into the tracer. 93 func (c ContextImpl) ImportNinjaLog(filename string, startOffset time.Time) { 94 if c.Tracer != nil { 95 c.Tracer.ImportNinjaLog(c.Thread, filename, startOffset) 96 } 97 } 98 99 func (c ContextImpl) IsTerminal() bool { 100 if term, ok := os.LookupEnv("TERM"); ok { 101 return term != "dumb" && isTerminal(c.Stdout()) && isTerminal(c.Stderr()) 102 } 103 return false 104 } 105 106 func (c ContextImpl) IsErrTerminal() bool { 107 if term, ok := os.LookupEnv("TERM"); ok { 108 return term != "dumb" && isTerminal(c.Stderr()) 109 } 110 return false 111 } 112 113 func (c ContextImpl) TermWidth() (int, bool) { 114 return termWidth(c.Stdout()) 115 } 116