github.com/metux/go-metabuild@v0.0.0-20240118143255-d9ed5ab697f9/spec/check/check.go (about) 1 package check 2 3 import ( 4 "fmt" 5 "log" 6 "os" 7 "strings" 8 9 "github.com/segmentio/fasthash/fnv1a" 10 11 "github.com/metux/go-metabuild/spec/buildconf" 12 "github.com/metux/go-metabuild/spec/cache" 13 "github.com/metux/go-metabuild/spec/distro" 14 "github.com/metux/go-metabuild/util" 15 "github.com/metux/go-metabuild/util/specobj" 16 ) 17 18 type Check struct { 19 specobj.SpecObj 20 Cache cache.Cache 21 BuildConf buildconf.BuildConf 22 Distros distro.Distro 23 } 24 25 type CheckList = []Check 26 27 // Check whether result already cached and return it 28 // -> (cached, cacheval) 29 func (chk Check) Cached() (bool, bool) { 30 return chk.Cache.CheckGet(chk.Hash()) 31 } 32 33 func (chk Check) IsMandatory() bool { 34 return chk.EntryBoolDef(KeyMandatory, false) 35 } 36 37 func (chk Check) IsDone() bool { 38 return chk.EntryBoolDef(KeyDone, false) 39 } 40 41 func (chk Check) IsPresent() bool { 42 return chk.EntryBoolDef(KeyPresent, false) 43 } 44 45 func (chk Check) ForBuild() bool { 46 return chk.EntryBoolDef(KeyBuild, false) 47 } 48 49 func (chk Check) TempDir() string { 50 return chk.BuildConf.BuildTempDir("checks/" + chk.Hash()) 51 } 52 53 func (chk Check) Done(succ bool) { 54 // FIXME: write to cache 55 chk.EntryPutBool(KeyPresent, succ) 56 chk.EntryPutBool(KeyDone, true) 57 } 58 59 // Compute a hash of the attributes that describing the check's tests, 60 // but skipping any other ones, eg. those telling what to do with the result 61 func (chk Check) Hash() string { 62 h := fnv1a.Init64 63 for _, x := range chk.EntryStrList(KeyHashAttrs) { 64 h = fnv1a.AddString64(h, chk.EntryStr(Key(x))) 65 } 66 return fmt.Sprintf("%X", h) 67 } 68 69 func (chk Check) Init() error { 70 if err := chk.detectCheckType(); err != nil { 71 return err 72 } 73 return chk.initFields() 74 } 75 76 func (chk Check) String() string { 77 h := chk.Type() + " " 78 for _, k := range chk.EntryStrList(KeyHashAttrs) { 79 if k != string(KeyType) { 80 h = fmt.Sprintf("%s %s=%s ", h, k, chk.EntryStrList(Key(k))) 81 } 82 } 83 return h + util.ValIf(chk.IsMandatory(), " (mandatory)", "") + " " + chk.Hash() 84 } 85 86 func (chk Check) TestProgFile(suffix string) string { 87 return fmt.Sprintf("%s/metabuild-check-%s-%s.%s", 88 os.TempDir(), util.ValIf(chk.ForBuild(), "build", "host"), 89 chk.Hash(), suffix) 90 } 91 92 func (chk Check) GetDefines() []string { 93 return chk.EntryStrList(KeyDefines) 94 } 95 96 func (chk Check) Type() string { 97 return chk.EntryStr(KeyType) 98 } 99 100 func (chk Check) detectCheckType() error { 101 if chk.Type() != "" { 102 return nil 103 } 104 105 types := []Key{ 106 // c-header needs to be last, since others may also have headers 107 KeyCFunction, 108 KeyCType, 109 KeyCHeader, 110 111 KeyPkgConfig, 112 } 113 114 for _, x := range types { 115 if s := chk.EntryStrList(x); len(s) > 0 { 116 chk.EntryPutStr(KeyType, string(x)) 117 return nil 118 } 119 } 120 121 return ErrUnsupportedCheck 122 } 123 124 func (chk Check) initFields() error { 125 chk.EntryPutStrList(KeyHashAttrs, []string{ 126 string(KeyType), 127 string(KeyCHeader), 128 string(KeyCFunction), 129 string(KeyCType), 130 string(KeyPkgConfig), 131 string(KeyBuild), 132 }) 133 return nil 134 } 135 136 func (chk Check) Id() string { 137 return chk.EntryStr(KeyId) 138 } 139 140 func (chk Check) SetId(id string) { 141 chk.EntryPutStr(KeyId, id) 142 } 143 144 func (chk Check) SetIdList(ids []string) []string { 145 chk.SetId(strings.Join(ids, " ")) 146 return ids 147 } 148 149 func (chk Check) YesNoStrList(yesno bool, k Key) []string { 150 return chk.EntryStrList(Key(util.YesNo(yesno) + "/" + string(k))) 151 } 152 153 func (chk Check) YesNoKey(yesno bool, k Key) Key { 154 return Key(util.YesNo(yesno) + "/" + string(k)) 155 } 156 157 func (chk Check) Logf(f string, args ...any) { 158 if id := chk.Id(); id == "" { 159 log.Printf("[Check %s] %s\n", chk.Type(), fmt.Sprintf(f, args...)) 160 } else { 161 log.Printf("[Check %s %s] %s\n", chk.Type(), id, fmt.Sprintf(f, args...)) 162 } 163 }