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  }