github.com/hwaf/hwaf@v0.0.0-20140814122253-5465f73b20f1/plugins/asetup/asetup.go (about) 1 package asetup 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "runtime" 9 "sort" 10 "strings" 11 12 "github.com/gonuts/commander" 13 gocfg "github.com/gonuts/config" 14 "github.com/hwaf/hwaf/hwaflib" 15 "github.com/hwaf/hwaf/platform" 16 ) 17 18 func path_exists(name string) bool { 19 _, err := os.Stat(name) 20 if err == nil { 21 return true 22 } 23 if os.IsNotExist(err) { 24 return false 25 } 26 return false 27 } 28 29 type asetup_t struct { 30 ctx *hwaflib.Context 31 cmd *commander.Command 32 args []string 33 opts options 34 verbose bool 35 } 36 37 type options struct { 38 projdir string 39 variant string 40 toolchain map[string]string // entries for the hwaf-toolchain section 41 env map[string]string // entries for the hwaf-env section 42 } 43 44 func new_options() options { 45 return options{ 46 toolchain: make(map[string]string), 47 env: make(map[string]string), 48 } 49 } 50 51 func Run(ctx *hwaflib.Context, cmd *commander.Command, args []string) error { 52 cfg := asetup_t{ 53 ctx: ctx, 54 cmd: cmd, 55 args: args, 56 opts: new_options(), 57 verbose: cmd.Flag.Lookup("v").Value.Get().(bool), 58 } 59 return cfg.run() 60 } 61 62 func (a *asetup_t) run() error { 63 var err error 64 65 n := "hwaf-" + a.cmd.Name() 66 67 if len(a.args) == 0 { 68 if a.verbose { 69 a.ctx.Infof("re-using previously asetup'ed workarea...\n") 70 } 71 // case where we reuse a previously already asetup'ed workarea 72 _, err = a.ctx.LocalCfg() 73 if err == nil { 74 if a.verbose { 75 a.ctx.Infof("re-using previously asetup'ed workarea... [done]\n") 76 } 77 return nil 78 } 79 err = fmt.Errorf("%v\n'hwaf asetup' called with no argument in a pristine workarea is NOT valid.", err) 80 if err != nil { 81 return err 82 } 83 } 84 85 args := make([]string, 0, len(a.args)) 86 for _, arg := range a.args { 87 subarg := strings.Split(arg, ",") 88 for _, sarg := range subarg { 89 if sarg != "" { 90 args = append(args, sarg) 91 } 92 } 93 } 94 95 dirname, err := os.Getwd() 96 if err != nil { 97 return err 98 } 99 100 dirname, err = filepath.Abs(dirname) 101 if err != nil { 102 return err 103 } 104 105 // make sure 'hwaf init' was run at least once in this directory... 106 for _, dir := range []string{ 107 filepath.Join(dirname, ".hwaf", "bin"), 108 filepath.Join(dirname, ".hwaf", "tools"), 109 } { 110 err = os.RemoveAll(dir) 111 if err != nil { 112 return err 113 } 114 } 115 { 116 sub := exec.Command("hwaf", "init", fmt.Sprintf("-v=%v", a.verbose), dirname) 117 sub.Stdin = os.Stdin 118 sub.Stdout = os.Stdout 119 sub.Stderr = os.Stderr 120 err = sub.Run() 121 if err != nil { 122 return err 123 } 124 } 125 126 err = a.process(args) 127 if err != nil { 128 return err 129 } 130 131 if a.verbose { 132 fmt.Printf("%s: asetup workarea [%s]...\n", n, dirname) 133 fmt.Printf("%s: projects=%v\n", n, a.opts.projdir) 134 // if cfg_fname != "" { 135 // fmt.Printf("%s: cfg-file=%s\n", n, cfg_fname) 136 // } 137 } 138 139 subcmd := exec.Command( 140 "hwaf", "setup", 141 fmt.Sprintf("-v=%v", a.verbose), 142 "-p", a.opts.projdir, 143 ) 144 subcmd.Stdin = os.Stdin 145 subcmd.Stdout = os.Stdout 146 subcmd.Stderr = os.Stderr 147 err = subcmd.Run() 148 if err != nil { 149 return err 150 } 151 152 lcfg_fname := "local.conf" 153 if !path_exists(lcfg_fname) { 154 err = fmt.Errorf("%s: no such file [%s]", n, lcfg_fname) 155 if err != nil { 156 return err 157 } 158 } 159 160 lcfg, err := gocfg.ReadDefault(lcfg_fname) 161 if err != nil { 162 return err 163 } 164 165 err = a.handle_toolchain_section(lcfg, lcfg_fname) 166 if err != nil { 167 return err 168 } 169 170 err = a.handle_env_section(lcfg, lcfg_fname, dirname) 171 if err != nil { 172 return err 173 } 174 175 err = lcfg.WriteFile(lcfg_fname, 0600, "") 176 if err != nil { 177 return err 178 } 179 180 if a.verbose { 181 fmt.Printf("%s: asetup workarea [%s]... [ok]\n", n, dirname) 182 } 183 return err 184 } 185 186 func infer_version(arg, projname string, version *string) bool { 187 ok := false 188 proj_table := map[string]string{ 189 "mana": "", 190 "lcg": "LCG_", 191 "tdaq": "tdaq-common-", 192 } 193 prefix, haskey := proj_table[projname] 194 if !haskey { 195 return false 196 } 197 for _, p := range []string{ 198 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 199 } { 200 if strings.HasPrefix(arg, prefix+p) { 201 *version = arg 202 return true 203 } 204 } 205 return ok 206 } 207 208 // FIXME: this should be more thought out... and structured! 209 func (a *asetup_t) process(args []string) error { 210 var err error 211 opts := new_options() 212 213 pinfos, err := platform.Infos() 214 if err != nil { 215 return err 216 } 217 218 //cfg_fname := a.cmd.Flag.Lookup("cfg").Value.Get().(string) 219 cli_variant := a.cmd.Flag.Lookup("variant").Value.Get().(string) 220 cli_arch := a.cmd.Flag.Lookup("arch").Value.Get().(string) 221 cli_comp := a.cmd.Flag.Lookup("comp").Value.Get().(string) 222 cli_os := a.cmd.Flag.Lookup("os").Value.Get().(string) 223 cli_type := a.cmd.Flag.Lookup("type").Value.Get().(string) 224 225 unprocessed := make([]string, 0, len(args)) 226 projname := "mana-core" 227 version := "" 228 hwaf_os := pinfos.DistId() 229 // fold slX into slcX (ie: all Scientific Linuces are SLCs) 230 if pinfos.DistName == "sl" { 231 rel := strings.Split(pinfos.DistVers, ".") 232 major := rel[0] 233 hwaf_os = "slc" + major 234 } 235 hwaf_comp := "gcc" 236 hwaf_arch := "" 237 switch runtime.GOARCH { 238 case "amd64": 239 hwaf_arch = "x86_64" 240 case "386": 241 hwaf_arch = "i686" 242 default: 243 //hwaf_arch = "unknown" 244 panic(fmt.Sprintf("unknown architecture [%s]", hwaf_arch)) 245 } 246 hwaf_bld := "opt" 247 for _, arg := range args { 248 has_prefix := func(prefix ...string) bool { 249 for _, p := range prefix { 250 ok := strings.HasPrefix(arg, p) 251 if ok { 252 return ok 253 } 254 } 255 return false 256 } 257 switch arg { 258 case "32b": 259 hwaf_arch = "i686" 260 case "64b": 261 hwaf_arch = "x86_64" 262 case "opt": 263 hwaf_bld = "opt" 264 case "dbg": 265 hwaf_bld = "dbg" 266 case "mana", "mana-core": 267 projname = "mana-core" 268 case "mana-ext", "lcg": 269 projname = arg 270 case "tdaq", "tdaq-common": 271 projname = "tdaq-common" 272 default: 273 if has_prefix( 274 "2012", "2013", 275 "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", 276 ) { 277 version = arg 278 } else if has_prefix("gcc") || has_prefix("clang") { 279 hwaf_comp = arg 280 } else if infer_version(arg, projname, &version) { 281 //version = version 282 } else { 283 unprocessed = append(unprocessed, arg) 284 } 285 } 286 } 287 if len(unprocessed) > 0 { 288 err = fmt.Errorf("unprocessed asetup options: %v", unprocessed) 289 } 290 291 // honour CLI args 292 for _, v := range [][]*string{ 293 {&cli_arch, &hwaf_arch}, 294 {&cli_os, &hwaf_os}, 295 {&cli_comp, &hwaf_comp}, 296 {&cli_type, &hwaf_bld}, 297 } { 298 if *v[0] != "" { 299 *v[1] = *v[0] 300 } 301 } 302 303 sitedir := a.ctx.Sitedir() 304 if sitedir == "" { 305 sitedir = filepath.Join("", "opt", "sw", "atlas") 306 a.ctx.Warnf("no $HWAF_SITEDIR env. variable. will use [%s]\n", sitedir) 307 } 308 309 if a.verbose { 310 a.ctx.Infof("using sitedir: [%s]\n", sitedir) 311 } 312 313 if !path_exists(sitedir) { 314 err = fmt.Errorf("no such directory [%s]", sitedir) 315 return err 316 } 317 318 usr_variant := fmt.Sprintf("%s-%s-%s-%s", hwaf_arch, hwaf_os, hwaf_comp, hwaf_bld) 319 proj_root := filepath.Join(sitedir, projname) 320 if !path_exists(proj_root) { 321 err = fmt.Errorf("no such directory [%s]", proj_root) 322 return err 323 } 324 325 if a.verbose { 326 a.ctx.Infof("using project root [%s]\n", proj_root) 327 } 328 329 if version == "" { 330 // get the latest one. 331 var versions []string 332 versions, err = filepath.Glob(filepath.Join(proj_root, "*")) 333 if err != nil { 334 return err 335 } 336 sort.Strings(versions) 337 version = versions[len(versions)-1] 338 version, _ = filepath.Abs(version) 339 version = filepath.Base(version) 340 } 341 opts.projdir = filepath.Join(proj_root, version) 342 if !path_exists(opts.projdir) { 343 err = fmt.Errorf("no such directory [%s]", opts.projdir) 344 return err 345 } 346 347 if a.verbose { 348 a.ctx.Infof("using project dir [%s]\n", opts.projdir) 349 } 350 351 // dft_variant is a variation on DefaultVariant. 352 dft_variant := fmt.Sprintf( 353 "%s-%s-%s-%s", 354 hwaf_arch, 355 hwaf_os, 356 strings.Split(a.ctx.DefaultVariant(), "-")[2], // compiler 357 hwaf_bld, 358 ) 359 360 found := false 361 for ii, variant := range []string{ 362 cli_variant, 363 usr_variant, 364 a.ctx.Variant(), 365 a.ctx.DefaultVariant(), 366 dft_variant, 367 } { 368 if variant == "" { 369 continue 370 } 371 dir := filepath.Join(opts.projdir, variant) 372 if a.verbose { 373 fmt.Printf("---> (%03d) [%s]... ", ii, dir) 374 } 375 if !path_exists(dir) { 376 if a.verbose { 377 fmt.Printf("[err]\n") 378 } 379 continue 380 } 381 opts.projdir = dir 382 opts.variant = variant 383 if a.verbose { 384 fmt.Printf("[ok]\n") 385 } 386 found = true 387 break 388 } 389 if !found { 390 return fmt.Errorf("hwaf: could not find a suitable project") 391 } 392 a.opts = opts 393 return err 394 } 395 396 func (a *asetup_t) handle_toolchain_section(lcfg *gocfg.Config, lcfg_fname string) error { 397 var err error 398 n := "hwaf-" + a.cmd.Name() 399 400 section := "hwaf-toolchain" 401 if !lcfg.HasSection(section) { 402 if !lcfg.AddSection(section) { 403 err = fmt.Errorf("%s: could not create section [%s] in file [%s]", 404 n, section, lcfg_fname) 405 if err != nil { 406 return err 407 } 408 } 409 } 410 for k, v := range a.opts.toolchain { 411 if lcfg.HasOption(section, k) { 412 lcfg.RemoveOption(section, k) 413 } 414 ok := lcfg.AddOption(section, k, v) 415 if !ok { 416 err = fmt.Errorf( 417 "%s: could not add option [%s=%q] to file [%s]", 418 n, k, v, lcfg_fname, 419 ) 420 if err != nil { 421 return err 422 } 423 } 424 } 425 return err 426 } 427 428 func (a *asetup_t) handle_env_section(lcfg *gocfg.Config, lcfg_fname, dirname string) error { 429 var err error 430 n := "hwaf-" + a.cmd.Name() 431 432 section := "hwaf-env" 433 if !lcfg.HasSection(section) { 434 if !lcfg.AddSection(section) { 435 err = fmt.Errorf("%s: could not create section [%s] in file [%s]", 436 n, section, lcfg_fname) 437 if err != nil { 438 return err 439 } 440 } 441 } 442 // add a few asetup defaults... 443 for k, v := range map[string]string{ 444 "SVNGROUPS": "svn+ssh://svn.cern.ch/reps/atlasgroups", 445 "SVNGRP": "svn+ssh://svn.cern.ch/reps/atlasgrp", 446 "SVNINST": "svn+ssh://svn.cern.ch/reps/atlasinst", 447 "SVNOFF": "svn+ssh://svn.cern.ch/reps/atlasoff", 448 "SVNPERF": "svn+ssh://svn.cern.ch/reps/atlasperf", 449 "SVNPHYS": "svn+ssh://svn.cern.ch/reps/atlasphys", 450 "SVNROOT": "svn+ssh://svn.cern.ch/reps/atlasoff", 451 "SVNUSR": "svn+ssh://svn.cern.ch/reps/atlasusr", 452 "TestArea": dirname, 453 } { 454 a.opts.env[k] = v 455 } 456 457 for k, v := range a.opts.env { 458 if lcfg.HasOption(section, k) { 459 lcfg.RemoveOption(section, k) 460 } 461 ok := lcfg.AddOption(section, k, v) 462 if !ok { 463 err = fmt.Errorf( 464 "%s: could not add option [%s=%q] to file [%s]", 465 n, k, v, lcfg_fname, 466 ) 467 if err != nil { 468 return err 469 } 470 } 471 } 472 473 return err 474 } 475 476 // EOF