github.com/metux/go-metabuild@v0.0.0-20240118143255-d9ed5ab697f9/spec/target/targetobject.go (about) 1 package target 2 3 import ( 4 "os" 5 "path/filepath" 6 "regexp" 7 8 "github.com/metux/go-metabuild/spec/buildconf" 9 "github.com/metux/go-metabuild/spec/cache" 10 "github.com/metux/go-metabuild/util" 11 "github.com/metux/go-metabuild/util/fileutil" 12 "github.com/metux/go-metabuild/util/specobj" 13 ) 14 15 var ( 16 reWithType = regexp.MustCompile(`(.*)\{([\w/_\-\.\+]+)\}$`) 17 ) 18 19 type TargetObject struct { 20 specobj.SpecObj 21 BuildConf buildconf.BuildConf 22 Cache cache.Cache 23 } 24 25 func (o TargetObject) FeaturedStrList(k Key) []string { 26 ret := o.EntryStrList(k) 27 for _, f := range o.BuildConf.Features.All() { 28 k2 := Key(string(k) + "@feature/" + string(f.Id) + "=" + f.ValueYN()) 29 ret = append(ret, o.EntryStrList(k2)...) 30 } 31 return ret 32 } 33 34 func (o TargetObject) Sources() []string { 35 res := []string{} 36 for _, f := range util.StrDirPrefix(o.EntryStr(KeySourceDir), o.FeaturedStrList(KeySource)) { 37 files, err := filepath.Glob(f) 38 util.ErrPanicf(err, "file glob error") 39 if len(files) == 0 { 40 panic("broken source glob: " + f) 41 } 42 res = append(res, files...) 43 } 44 return res 45 } 46 47 func (o TargetObject) RequiredSources() []string { 48 s := util.StrDirPrefix(o.EntryStr(KeySourceDir), o.FeaturedStrList(KeySource)) 49 if len(s) == 0 { 50 panic("source attribute required") 51 } 52 return s 53 } 54 55 func (o TargetObject) RequiredSourceAbs() string { 56 s := o.RequiredSources() 57 if len(s) != 1 { 58 panic("only exactly one source file required") 59 } 60 a, err := filepath.Abs(s[0]) 61 util.ErrPanicf(err, "failed retrieving absolute path of %s", s[0]) 62 return a 63 } 64 65 func (o TargetObject) ForBuild() bool { 66 return o.EntryBoolDef(Key("build"), false) 67 } 68 69 func (o TargetObject) MyId() string { 70 return o.EntryStr(KeyInternId) 71 } 72 73 func (o TargetObject) loadTargetType(t Key) { 74 if !t.Empty() { 75 k := buildconf.KeyTargetPlatform.Append("targets").Append(t).MagicLiteralPost() 76 o.CopyDefaultsFrom(o.BuildConf.EntrySpec(k)) 77 } 78 } 79 80 func (o TargetObject) setId(id string) { 81 o.EntryPutStr(KeyInternId, id) 82 if ext := filepath.Ext(id); ext != "" { 83 o.DefaultPutStr(KeyInternIdSuffix, ext[1:]) 84 } 85 86 o.DefaultPutStr(KeyInternBasename, filepath.Base(id)) 87 88 if dn := filepath.Dir(id); dn != "" { 89 o.DefaultPutStr(KeyInternDirname, dn) 90 } 91 } 92 93 func (o TargetObject) LoadTargetDefaults() { 94 id := o.MyKey() 95 96 if match := reWithType.FindStringSubmatch(string(id)); len(match) == 3 { 97 o.setId(match[1]) 98 o.EntryPutStr(KeyInternType, match[2]) 99 o.loadTargetType(Key(match[2])) 100 } else { 101 o.setId(string(id)) 102 } 103 104 o.loadTargetType(o.Type()) 105 } 106 107 func (o TargetObject) CDefines() []string { 108 return o.FeaturedStrList(KeyCDefines) 109 } 110 111 func (o TargetObject) CFlags() []string { 112 return o.FeaturedStrList(KeyCCflags) 113 } 114 115 func (o TargetObject) GetFMode(k Key) os.FileMode { 116 n, _ := fileutil.FileModeParse(o.EntryStr(k)) 117 return n 118 } 119 120 func (o TargetObject) InstallPerm() os.FileMode { 121 m, err := fileutil.FileModeParse(o.RequiredEntryStr(KeyInstallPerm)) 122 if m == 0 || err != nil { 123 util.Panicf("config error: target's mode=0 or error %s", err) 124 } 125 return m 126 } 127 128 func (o TargetObject) InstallDir() string { 129 return o.RequiredEntryStr(KeyInstallDir) + "/" + o.EntryStr(KeyInstallSubdir) 130 } 131 132 func (o TargetObject) PackageId(scope string) string { 133 k := Key(scope + string(KeyInstallPackage)) 134 id := o.EntryStr(k) 135 if id == "" { 136 panic("config error: PackageId empty") 137 } 138 return id 139 } 140 141 func (o TargetObject) CompilerLang() string { 142 return o.RequiredEntryStr(KeyCompilerLang) 143 } 144 145 func (o TargetObject) Type() Key { 146 if s := o.EntryStr(KeyInternType); s != "" { 147 return Key(s) 148 } 149 return Key(o.EntryStr(KeyType)) 150 } 151 152 func (o TargetObject) SetType(k Key) { 153 o.EntryPutStr(KeyType, string(k)) 154 } 155 156 func (o TargetObject) SubTarget(k specobj.Key) TargetObject { 157 return MakeTargetObject(o.EntrySpec(k), k, o.BuildConf, o.Cache) 158 } 159 160 func (o TargetObject) WantInstall() bool { 161 return o.EntryBoolDef(KeyInstall, true) 162 } 163 164 func (b TargetObject) EntryPathList(k Key) []string { 165 list := b.EntryStrList(k) 166 for idx, ent := range list { 167 d, err := filepath.Abs(ent) 168 util.ErrPanicf(err, "error retrieving abspath for %s", d) 169 list[idx] = d 170 } 171 return list 172 } 173 174 func (o TargetObject) Skipped() bool { 175 if o.EntryBoolDef(KeySkip, false) { 176 return true 177 } 178 179 for _, opt := range o.EntryStrList(KeyOptional) { 180 f := o.BuildConf.Features.Get(Key(opt)) 181 if !f.IsOn() { 182 return true 183 } 184 } 185 186 return false 187 } 188 189 func MakeTargetObject(spec specobj.SpecObj, k Key, bc buildconf.BuildConf, c cache.Cache) TargetObject { 190 obj := TargetObject{ 191 SpecObj: spec, 192 Cache: c, 193 BuildConf: bc, 194 } 195 return obj 196 }