github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/dist/build.c (about) 1 // Copyright 2012 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include "a.h" 6 #include "arg.h" 7 8 /* 9 * Initialization for any invocation. 10 */ 11 12 // The usual variables. 13 char *goarch; 14 char *gobin; 15 char *gohostarch; 16 char *gohostchar; 17 char *gohostos; 18 char *goos; 19 char *goarm; 20 char *go386; 21 char *goroot = GOROOT_FINAL; 22 char *goroot_final = GOROOT_FINAL; 23 char *goextlinkenabled = ""; 24 char *workdir; 25 char *tooldir; 26 char *gochar; 27 char *goversion; 28 char *slash; // / for unix, \ for windows 29 30 bool rebuildall = 0; 31 32 static bool shouldbuild(char*, char*); 33 static void copy(char*, char*, int); 34 static char *findgoversion(void); 35 36 // The known architecture letters. 37 static char *gochars = "568"; 38 39 // The known architectures. 40 static char *okgoarch[] = { 41 // same order as gochars 42 "arm", 43 "amd64", 44 "386", 45 }; 46 47 // The known operating systems. 48 static char *okgoos[] = { 49 "darwin", 50 "linux", 51 "freebsd", 52 "netbsd", 53 "openbsd", 54 "plan9", 55 "windows", 56 }; 57 58 static void rmworkdir(void); 59 60 // find reports the first index of p in l[0:n], or else -1. 61 int 62 find(char *p, char **l, int n) 63 { 64 int i; 65 66 for(i=0; i<n; i++) 67 if(streq(p, l[i])) 68 return i; 69 return -1; 70 } 71 72 // init handles initialization of the various global state, like goroot and goarch. 73 void 74 init(void) 75 { 76 char *p; 77 int i; 78 Buf b; 79 80 binit(&b); 81 82 xgetenv(&b, "GOROOT"); 83 if(b.len > 0) { 84 // if not "/", then strip trailing path separator 85 if(b.len >= 2 && b.p[b.len - 1] == slash[0]) 86 b.len--; 87 goroot = btake(&b); 88 } 89 90 xgetenv(&b, "GOBIN"); 91 if(b.len == 0) 92 bprintf(&b, "%s%sbin", goroot, slash); 93 gobin = btake(&b); 94 95 xgetenv(&b, "GOOS"); 96 if(b.len == 0) 97 bwritestr(&b, gohostos); 98 goos = btake(&b); 99 if(find(goos, okgoos, nelem(okgoos)) < 0) 100 fatal("unknown $GOOS %s", goos); 101 102 xgetenv(&b, "GOARM"); 103 if(b.len == 0) 104 bwritestr(&b, xgetgoarm()); 105 goarm = btake(&b); 106 107 xgetenv(&b, "GO386"); 108 if(b.len == 0) { 109 if(cansse2()) 110 bwritestr(&b, "sse2"); 111 else 112 bwritestr(&b, "387"); 113 } 114 go386 = btake(&b); 115 116 p = bpathf(&b, "%s/include/u.h", goroot); 117 if(!isfile(p)) { 118 fatal("$GOROOT is not set correctly or not exported\n" 119 "\tGOROOT=%s\n" 120 "\t%s does not exist", goroot, p); 121 } 122 123 xgetenv(&b, "GOHOSTARCH"); 124 if(b.len > 0) 125 gohostarch = btake(&b); 126 127 i = find(gohostarch, okgoarch, nelem(okgoarch)); 128 if(i < 0) 129 fatal("unknown $GOHOSTARCH %s", gohostarch); 130 bprintf(&b, "%c", gochars[i]); 131 gohostchar = btake(&b); 132 133 xgetenv(&b, "GOARCH"); 134 if(b.len == 0) 135 bwritestr(&b, gohostarch); 136 goarch = btake(&b); 137 i = find(goarch, okgoarch, nelem(okgoarch)); 138 if(i < 0) 139 fatal("unknown $GOARCH %s", goarch); 140 bprintf(&b, "%c", gochars[i]); 141 gochar = btake(&b); 142 143 xgetenv(&b, "GO_EXTLINK_ENABLED"); 144 if(b.len > 0) { 145 goextlinkenabled = btake(&b); 146 if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1")) 147 fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled); 148 } 149 150 xsetenv("GOROOT", goroot); 151 xsetenv("GOARCH", goarch); 152 xsetenv("GOOS", goos); 153 xsetenv("GOARM", goarm); 154 xsetenv("GO386", go386); 155 156 // Make the environment more predictable. 157 xsetenv("LANG", "C"); 158 xsetenv("LANGUAGE", "en_US.UTF8"); 159 160 goversion = findgoversion(); 161 162 workdir = xworkdir(); 163 xatexit(rmworkdir); 164 165 bpathf(&b, "%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch); 166 tooldir = btake(&b); 167 168 bfree(&b); 169 } 170 171 // rmworkdir deletes the work directory. 172 static void 173 rmworkdir(void) 174 { 175 if(vflag > 1) 176 errprintf("rm -rf %s\n", workdir); 177 xremoveall(workdir); 178 } 179 180 // Remove trailing spaces. 181 static void 182 chomp(Buf *b) 183 { 184 int c; 185 186 while(b->len > 0 && ((c=b->p[b->len-1]) == ' ' || c == '\t' || c == '\r' || c == '\n')) 187 b->len--; 188 } 189 190 191 // findgoversion determines the Go version to use in the version string. 192 static char* 193 findgoversion(void) 194 { 195 char *tag, *rev, *p; 196 int i, nrev; 197 Buf b, path, bmore, branch; 198 Vec tags; 199 200 binit(&b); 201 binit(&path); 202 binit(&bmore); 203 binit(&branch); 204 vinit(&tags); 205 206 // The $GOROOT/VERSION file takes priority, for distributions 207 // without the Mercurial repo. 208 bpathf(&path, "%s/VERSION", goroot); 209 if(isfile(bstr(&path))) { 210 readfile(&b, bstr(&path)); 211 chomp(&b); 212 // Commands such as "dist version > VERSION" will cause 213 // the shell to create an empty VERSION file and set dist's 214 // stdout to its fd. dist in turn looks at VERSION and uses 215 // its content if available, which is empty at this point. 216 if(b.len > 0) 217 goto done; 218 } 219 220 // The $GOROOT/VERSION.cache file is a cache to avoid invoking 221 // hg every time we run this command. Unlike VERSION, it gets 222 // deleted by the clean command. 223 bpathf(&path, "%s/VERSION.cache", goroot); 224 if(isfile(bstr(&path))) { 225 readfile(&b, bstr(&path)); 226 chomp(&b); 227 goto done; 228 } 229 230 // Otherwise, use Mercurial. 231 // What is the current branch? 232 run(&branch, goroot, CheckExit, "hg", "identify", "-b", nil); 233 chomp(&branch); 234 235 // What are the tags along the current branch? 236 tag = "devel"; 237 rev = "."; 238 run(&b, goroot, CheckExit, "hg", "log", "-b", bstr(&branch), "-r", ".:0", "--template", "{tags} + ", nil); 239 splitfields(&tags, bstr(&b)); 240 nrev = 0; 241 for(i=0; i<tags.len; i++) { 242 p = tags.p[i]; 243 if(streq(p, "+")) 244 nrev++; 245 // NOTE: Can reenable the /* */ code when we want to 246 // start reporting versions named 'weekly' again. 247 if(/*hasprefix(p, "weekly.") ||*/ hasprefix(p, "go")) { 248 tag = xstrdup(p); 249 // If this tag matches the current checkout 250 // exactly (no "+" yet), don't show extra 251 // revision information. 252 if(nrev == 0) 253 rev = ""; 254 break; 255 } 256 } 257 258 if(tag[0] == '\0') { 259 // Did not find a tag; use branch name. 260 bprintf(&b, "branch.%s", bstr(&branch)); 261 tag = btake(&b); 262 } 263 264 if(rev[0]) { 265 // Tag is before the revision we're building. 266 // Add extra information. 267 run(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil); 268 chomp(&bmore); 269 } 270 271 bprintf(&b, "%s", tag); 272 if(bmore.len > 0) 273 bwriteb(&b, &bmore); 274 275 // Cache version. 276 writefile(&b, bstr(&path), 0); 277 278 done: 279 p = btake(&b); 280 281 282 bfree(&b); 283 bfree(&path); 284 bfree(&bmore); 285 bfree(&branch); 286 vfree(&tags); 287 288 return p; 289 } 290 291 /* 292 * Initial tree setup. 293 */ 294 295 // The old tools that no longer live in $GOBIN or $GOROOT/bin. 296 static char *oldtool[] = { 297 "5a", "5c", "5g", "5l", 298 "6a", "6c", "6g", "6l", 299 "8a", "8c", "8g", "8l", 300 "6cov", 301 "6nm", 302 "6prof", 303 "cgo", 304 "ebnflint", 305 "goapi", 306 "gofix", 307 "goinstall", 308 "gomake", 309 "gopack", 310 "gopprof", 311 "gotest", 312 "gotype", 313 "govet", 314 "goyacc", 315 "quietgcc", 316 }; 317 318 // Unreleased directories (relative to $GOROOT) that should 319 // not be in release branches. 320 static char *unreleased[] = { 321 "src/cmd/cov", 322 "src/cmd/prof", 323 "src/pkg/old", 324 }; 325 326 // setup sets up the tree for the initial build. 327 static void 328 setup(void) 329 { 330 int i; 331 Buf b; 332 char *p; 333 334 binit(&b); 335 336 // Create bin directory. 337 p = bpathf(&b, "%s/bin", goroot); 338 if(!isdir(p)) 339 xmkdir(p); 340 341 // Create package directory. 342 p = bpathf(&b, "%s/pkg", goroot); 343 if(!isdir(p)) 344 xmkdir(p); 345 p = bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch); 346 if(rebuildall) 347 xremoveall(p); 348 xmkdirall(p); 349 if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) { 350 p = bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch); 351 if(rebuildall) 352 xremoveall(p); 353 xmkdirall(p); 354 } 355 356 // Create object directory. 357 // We keep it in pkg/ so that all the generated binaries 358 // are in one tree. If pkg/obj/libgc.a exists, it is a dreg from 359 // before we used subdirectories of obj. Delete all of obj 360 // to clean up. 361 bpathf(&b, "%s/pkg/obj/libgc.a", goroot); 362 if(isfile(bstr(&b))) 363 xremoveall(bpathf(&b, "%s/pkg/obj", goroot)); 364 p = bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch); 365 if(rebuildall) 366 xremoveall(p); 367 xmkdirall(p); 368 369 // Create tool directory. 370 // We keep it in pkg/, just like the object directory above. 371 if(rebuildall) 372 xremoveall(tooldir); 373 xmkdirall(tooldir); 374 375 // Remove tool binaries from before the tool/gohostos_gohostarch 376 xremoveall(bpathf(&b, "%s/bin/tool", goroot)); 377 378 // Remove old pre-tool binaries. 379 for(i=0; i<nelem(oldtool); i++) 380 xremove(bpathf(&b, "%s/bin/%s", goroot, oldtool[i])); 381 382 // If $GOBIN is set and has a Go compiler, it must be cleaned. 383 for(i=0; gochars[i]; i++) { 384 if(isfile(bprintf(&b, "%s%s%c%s", gobin, slash, gochars[i], "g"))) { 385 for(i=0; i<nelem(oldtool); i++) 386 xremove(bprintf(&b, "%s%s%s", gobin, slash, oldtool[i])); 387 break; 388 } 389 } 390 391 // For release, make sure excluded things are excluded. 392 if(hasprefix(goversion, "release.") || hasprefix(goversion, "go")) { 393 for(i=0; i<nelem(unreleased); i++) 394 if(isdir(bpathf(&b, "%s/%s", goroot, unreleased[i]))) 395 fatal("%s should not exist in release build", bstr(&b)); 396 } 397 398 bfree(&b); 399 } 400 401 /* 402 * C library and tool building 403 */ 404 405 // gccargs is the gcc command line to use for compiling a single C file. 406 static char *proto_gccargs[] = { 407 "-Wall", 408 // native Plan 9 compilers don't like non-standard prototypes 409 // so let gcc catch them. 410 "-Wstrict-prototypes", 411 "-Wno-sign-compare", 412 "-Wno-missing-braces", 413 "-Wno-parentheses", 414 "-Wno-unknown-pragmas", 415 "-Wno-switch", 416 "-Wno-comment", 417 "-Werror", 418 "-fno-common", 419 "-ggdb", 420 "-pipe", 421 #if defined(__NetBSD__) && defined(__arm__) 422 // GCC 4.5.4 (NetBSD nb1 20120916) on ARM is known to mis-optimize gc/mparith3.c 423 // Fix available at http://patchwork.ozlabs.org/patch/64562/. 424 "-O1", 425 #else 426 "-O2", 427 #endif 428 }; 429 430 static Vec gccargs; 431 432 // deptab lists changes to the default dependencies for a given prefix. 433 // deps ending in /* read the whole directory; deps beginning with - 434 // exclude files with that prefix. 435 static struct { 436 char *prefix; // prefix of target 437 char *dep[20]; // dependency tweaks for targets with that prefix 438 } deptab[] = { 439 {"lib9", { 440 "$GOROOT/include/u.h", 441 "$GOROOT/include/utf.h", 442 "$GOROOT/include/fmt.h", 443 "$GOROOT/include/libc.h", 444 "fmt/*", 445 "utf/*", 446 }}, 447 {"libbio", { 448 "$GOROOT/include/u.h", 449 "$GOROOT/include/utf.h", 450 "$GOROOT/include/fmt.h", 451 "$GOROOT/include/libc.h", 452 "$GOROOT/include/bio.h", 453 }}, 454 {"libmach", { 455 "$GOROOT/include/u.h", 456 "$GOROOT/include/utf.h", 457 "$GOROOT/include/fmt.h", 458 "$GOROOT/include/libc.h", 459 "$GOROOT/include/bio.h", 460 "$GOROOT/include/ar.h", 461 "$GOROOT/include/bootexec.h", 462 "$GOROOT/include/mach.h", 463 "$GOROOT/include/ureg_amd64.h", 464 "$GOROOT/include/ureg_arm.h", 465 "$GOROOT/include/ureg_x86.h", 466 }}, 467 {"cmd/cc", { 468 "-pgen.c", 469 "-pswt.c", 470 }}, 471 {"cmd/gc", { 472 "-cplx.c", 473 "-pgen.c", 474 "-y1.tab.c", // makefile dreg 475 "opnames.h", 476 }}, 477 {"cmd/5c", { 478 "../cc/pgen.c", 479 "../cc/pswt.c", 480 "../5l/enam.c", 481 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", 482 }}, 483 {"cmd/6c", { 484 "../cc/pgen.c", 485 "../cc/pswt.c", 486 "../6l/enam.c", 487 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", 488 }}, 489 {"cmd/8c", { 490 "../cc/pgen.c", 491 "../cc/pswt.c", 492 "../8l/enam.c", 493 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libcc.a", 494 }}, 495 {"cmd/5g", { 496 "../gc/cplx.c", 497 "../gc/pgen.c", 498 "../5l/enam.c", 499 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", 500 }}, 501 {"cmd/6g", { 502 "../gc/cplx.c", 503 "../gc/pgen.c", 504 "../6l/enam.c", 505 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", 506 }}, 507 {"cmd/8g", { 508 "../gc/cplx.c", 509 "../gc/pgen.c", 510 "../8l/enam.c", 511 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libgc.a", 512 }}, 513 {"cmd/5l", { 514 "../ld/*", 515 "enam.c", 516 }}, 517 {"cmd/6l", { 518 "../ld/*", 519 "enam.c", 520 }}, 521 {"cmd/8l", { 522 "../ld/*", 523 "enam.c", 524 }}, 525 {"cmd/", { 526 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libmach.a", 527 "$GOROOT/pkg/obj/$GOOS_$GOARCH/libbio.a", 528 "$GOROOT/pkg/obj/$GOOS_$GOARCH/lib9.a", 529 }}, 530 {"pkg/runtime", { 531 "zasm_$GOOS_$GOARCH.h", 532 "zgoarch_$GOARCH.go", 533 "zgoos_$GOOS.go", 534 "zruntime_defs_$GOOS_$GOARCH.go", 535 "zversion.go", 536 }}, 537 }; 538 539 // depsuffix records the allowed suffixes for source files. 540 char *depsuffix[] = { 541 ".c", 542 ".h", 543 ".s", 544 ".go", 545 ".goc", 546 }; 547 548 // gentab records how to generate some trivial files. 549 static struct { 550 char *nameprefix; 551 void (*gen)(char*, char*); 552 } gentab[] = { 553 {"opnames.h", gcopnames}, 554 {"enam.c", mkenam}, 555 {"zasm_", mkzasm}, 556 {"zgoarch_", mkzgoarch}, 557 {"zgoos_", mkzgoos}, 558 {"zruntime_defs_", mkzruntimedefs}, 559 {"zversion.go", mkzversion}, 560 }; 561 562 // install installs the library, package, or binary associated with dir, 563 // which is relative to $GOROOT/src. 564 static void 565 install(char *dir) 566 { 567 char *name, *p, *elem, *prefix, *exe; 568 bool islib, ispkg, isgo, stale, clang; 569 Buf b, b1, path; 570 Vec compile, files, link, go, missing, clean, lib, extra; 571 Time ttarg, t; 572 int i, j, k, n, doclean, targ, usecpp; 573 574 if(vflag) { 575 if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) 576 errprintf("%s (%s/%s)\n", dir, goos, goarch); 577 else 578 errprintf("%s\n", dir); 579 } 580 581 binit(&b); 582 binit(&b1); 583 binit(&path); 584 vinit(&compile); 585 vinit(&files); 586 vinit(&link); 587 vinit(&go); 588 vinit(&missing); 589 vinit(&clean); 590 vinit(&lib); 591 vinit(&extra); 592 593 594 // path = full path to dir. 595 bpathf(&path, "%s/src/%s", goroot, dir); 596 name = lastelem(dir); 597 598 // For misc/prof, copy into the tool directory and we're done. 599 if(hasprefix(dir, "misc/")) { 600 copy(bpathf(&b, "%s/%s", tooldir, name), 601 bpathf(&b1, "%s/misc/%s", goroot, name), 1); 602 goto out; 603 } 604 605 // For release, cmd/prof and cmd/cov are not included. 606 if((streq(dir, "cmd/cov") || streq(dir, "cmd/prof")) && !isdir(bstr(&path))) { 607 if(vflag > 1) 608 errprintf("skipping %s - does not exist\n", dir); 609 goto out; 610 } 611 612 // set up gcc command line on first run. 613 if(gccargs.len == 0) { 614 xgetenv(&b, "CC"); 615 if(b.len == 0) 616 bprintf(&b, "gcc"); 617 clang = contains(bstr(&b), "clang"); 618 splitfields(&gccargs, bstr(&b)); 619 for(i=0; i<nelem(proto_gccargs); i++) 620 vadd(&gccargs, proto_gccargs[i]); 621 if(clang) { 622 // clang is too smart about unused command-line arguments 623 vadd(&gccargs, "-Qunused-arguments"); 624 } 625 if(streq(gohostos, "darwin")) { 626 // golang.org/issue/5261 627 vadd(&gccargs, "-mmacosx-version-min=10.6"); 628 } 629 } 630 631 islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc"); 632 ispkg = hasprefix(dir, "pkg"); 633 isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo"); 634 635 exe = ""; 636 if(streq(gohostos, "windows")) 637 exe = ".exe"; 638 639 // Start final link command line. 640 // Note: code below knows that link.p[targ] is the target. 641 if(islib) { 642 // C library. 643 vadd(&link, "ar"); 644 if(streq(gohostos, "plan9")) 645 vadd(&link, "rc"); 646 else 647 vadd(&link, "rsc"); 648 prefix = ""; 649 if(!hasprefix(name, "lib")) 650 prefix = "lib"; 651 targ = link.len; 652 vadd(&link, bpathf(&b, "%s/pkg/obj/%s_%s/%s%s.a", goroot, gohostos, gohostarch, prefix, name)); 653 } else if(ispkg) { 654 // Go library (package). 655 vadd(&link, bpathf(&b, "%s/pack", tooldir)); 656 vadd(&link, "grc"); 657 p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir+4); 658 *xstrrchr(p, '/') = '\0'; 659 xmkdirall(p); 660 targ = link.len; 661 vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir+4)); 662 } else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) { 663 // Go command. 664 vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar)); 665 vadd(&link, "-o"); 666 elem = name; 667 if(streq(elem, "go")) 668 elem = "go_bootstrap"; 669 targ = link.len; 670 vadd(&link, bpathf(&b, "%s/%s%s", tooldir, elem, exe)); 671 } else { 672 // C command. Use gccargs. 673 if(streq(gohostos, "plan9")) { 674 vadd(&link, bprintf(&b, "%sl", gohostchar)); 675 vadd(&link, "-o"); 676 targ = link.len; 677 vadd(&link, bpathf(&b, "%s/%s", tooldir, name)); 678 } else { 679 vcopy(&link, gccargs.p, gccargs.len); 680 vadd(&link, "-o"); 681 targ = link.len; 682 vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe)); 683 if(streq(gohostarch, "amd64")) 684 vadd(&link, "-m64"); 685 else if(streq(gohostarch, "386")) 686 vadd(&link, "-m32"); 687 } 688 } 689 ttarg = mtime(link.p[targ]); 690 691 // Gather files that are sources for this target. 692 // Everything in that directory, and any target-specific 693 // additions. 694 xreaddir(&files, bstr(&path)); 695 696 // Remove files beginning with . or _, 697 // which are likely to be editor temporary files. 698 // This is the same heuristic build.ScanDir uses. 699 // There do exist real C files beginning with _, 700 // so limit that check to just Go files. 701 n = 0; 702 for(i=0; i<files.len; i++) { 703 p = files.p[i]; 704 if(hasprefix(p, ".") || (hasprefix(p, "_") && hassuffix(p, ".go"))) 705 xfree(p); 706 else 707 files.p[n++] = p; 708 } 709 files.len = n; 710 711 for(i=0; i<nelem(deptab); i++) { 712 if(hasprefix(dir, deptab[i].prefix)) { 713 for(j=0; (p=deptab[i].dep[j])!=nil; j++) { 714 breset(&b1); 715 bwritestr(&b1, p); 716 bsubst(&b1, "$GOROOT", goroot); 717 bsubst(&b1, "$GOOS", goos); 718 bsubst(&b1, "$GOARCH", goarch); 719 p = bstr(&b1); 720 if(hassuffix(p, ".a")) { 721 if(streq(gohostos, "plan9") && hassuffix(p, "libbio.a")) 722 continue; 723 vadd(&lib, bpathf(&b, "%s", p)); 724 continue; 725 } 726 if(hassuffix(p, "/*")) { 727 bpathf(&b, "%s/%s", bstr(&path), p); 728 b.len -= 2; 729 xreaddir(&extra, bstr(&b)); 730 bprintf(&b, "%s", p); 731 b.len -= 2; 732 for(k=0; k<extra.len; k++) 733 vadd(&files, bpathf(&b1, "%s/%s", bstr(&b), extra.p[k])); 734 continue; 735 } 736 if(hasprefix(p, "-")) { 737 p++; 738 n = 0; 739 for(k=0; k<files.len; k++) { 740 if(hasprefix(files.p[k], p)) 741 xfree(files.p[k]); 742 else 743 files.p[n++] = files.p[k]; 744 } 745 files.len = n; 746 continue; 747 } 748 vadd(&files, p); 749 } 750 } 751 } 752 vuniq(&files); 753 754 // Convert to absolute paths. 755 for(i=0; i<files.len; i++) { 756 if(!isabs(files.p[i])) { 757 bpathf(&b, "%s/%s", bstr(&path), files.p[i]); 758 xfree(files.p[i]); 759 files.p[i] = btake(&b); 760 } 761 } 762 763 // Is the target up-to-date? 764 stale = rebuildall; 765 n = 0; 766 for(i=0; i<files.len; i++) { 767 p = files.p[i]; 768 for(j=0; j<nelem(depsuffix); j++) 769 if(hassuffix(p, depsuffix[j])) 770 goto ok; 771 xfree(files.p[i]); 772 continue; 773 ok: 774 t = mtime(p); 775 if(t != 0 && !hassuffix(p, ".a") && !shouldbuild(p, dir)) { 776 xfree(files.p[i]); 777 continue; 778 } 779 if(hassuffix(p, ".go")) 780 vadd(&go, p); 781 if(t > ttarg) 782 stale = 1; 783 if(t == 0) { 784 vadd(&missing, p); 785 files.p[n++] = files.p[i]; 786 continue; 787 } 788 files.p[n++] = files.p[i]; 789 } 790 files.len = n; 791 792 // If there are no files to compile, we're done. 793 if(files.len == 0) 794 goto out; 795 796 for(i=0; i<lib.len && !stale; i++) 797 if(mtime(lib.p[i]) > ttarg) 798 stale = 1; 799 800 if(!stale) 801 goto out; 802 803 // For package runtime, copy some files into the work space. 804 if(streq(dir, "pkg/runtime")) { 805 copy(bpathf(&b, "%s/arch_GOARCH.h", workdir), 806 bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0); 807 copy(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir), 808 bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0); 809 p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch); 810 if(isfile(p)) 811 copy(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0); 812 copy(bpathf(&b, "%s/os_GOOS.h", workdir), 813 bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0); 814 copy(bpathf(&b, "%s/signals_GOOS.h", workdir), 815 bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0); 816 } 817 818 // Generate any missing files; regenerate existing ones. 819 for(i=0; i<files.len; i++) { 820 p = files.p[i]; 821 elem = lastelem(p); 822 for(j=0; j<nelem(gentab); j++) { 823 if(hasprefix(elem, gentab[j].nameprefix)) { 824 if(vflag > 1) 825 errprintf("generate %s\n", p); 826 gentab[j].gen(bstr(&path), p); 827 // Do not add generated file to clean list. 828 // In pkg/runtime, we want to be able to 829 // build the package with the go tool, 830 // and it assumes these generated files already 831 // exist (it does not know how to build them). 832 // The 'clean' command can remove 833 // the generated files. 834 goto built; 835 } 836 } 837 // Did not rebuild p. 838 if(find(p, missing.p, missing.len) >= 0) 839 fatal("missing file %s", p); 840 built:; 841 } 842 843 // One more copy for package runtime. 844 // The last batch was required for the generators. 845 // This one is generated. 846 if(streq(dir, "pkg/runtime")) { 847 copy(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir), 848 bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0); 849 } 850 851 // Generate .c files from .goc files. 852 if(streq(dir, "pkg/runtime")) { 853 for(i=0; i<files.len; i++) { 854 p = files.p[i]; 855 if(!hassuffix(p, ".goc")) 856 continue; 857 // b = path/zp but with _goos_goarch.c instead of .goc 858 bprintf(&b, "%s%sz%s", bstr(&path), slash, lastelem(p)); 859 b.len -= 4; 860 bwritef(&b, "_%s_%s.c", goos, goarch); 861 goc2c(p, bstr(&b)); 862 vadd(&files, bstr(&b)); 863 } 864 vuniq(&files); 865 } 866 867 if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) { 868 // We've generated the right files; the go command can do the build. 869 if(vflag > 1) 870 errprintf("skip build for cross-compile %s\n", dir); 871 goto nobuild; 872 } 873 874 // The files generated by GNU Bison use macros that aren't 875 // supported by the Plan 9 compilers so we have to use the 876 // external preprocessor when compiling. 877 usecpp = 0; 878 if(streq(gohostos, "plan9")) { 879 for(i=0; i<files.len; i++) { 880 p = files.p[i]; 881 if(hassuffix(p, "y.tab.c") || hassuffix(p, "y.tab.h")){ 882 usecpp = 1; 883 break; 884 } 885 } 886 } 887 888 // Compile the files. 889 for(i=0; i<files.len; i++) { 890 if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s")) 891 continue; 892 name = lastelem(files.p[i]); 893 894 vreset(&compile); 895 if(!isgo) { 896 // C library or tool. 897 if(streq(gohostos, "plan9")) { 898 vadd(&compile, bprintf(&b, "%sc", gohostchar)); 899 vadd(&compile, "-FTVw"); 900 if(usecpp) 901 vadd(&compile, "-Bp+"); 902 vadd(&compile, bpathf(&b, "-I%s/include/plan9", goroot)); 903 vadd(&compile, bpathf(&b, "-I%s/include/plan9/%s", goroot, gohostarch)); 904 } else { 905 vcopy(&compile, gccargs.p, gccargs.len); 906 vadd(&compile, "-c"); 907 if(streq(gohostarch, "amd64")) 908 vadd(&compile, "-m64"); 909 else if(streq(gohostarch, "386")) 910 vadd(&compile, "-m32"); 911 if(streq(dir, "lib9")) 912 vadd(&compile, "-DPLAN9PORT"); 913 914 vadd(&compile, "-I"); 915 vadd(&compile, bpathf(&b, "%s/include", goroot)); 916 } 917 918 vadd(&compile, "-I"); 919 vadd(&compile, bstr(&path)); 920 921 // lib9/goos.c gets the default constants hard-coded. 922 if(streq(name, "goos.c")) { 923 vadd(&compile, "-D"); 924 vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos)); 925 vadd(&compile, "-D"); 926 vadd(&compile, bprintf(&b, "GOARCH=\"%s\"", goarch)); 927 bprintf(&b1, "%s", goroot_final); 928 bsubst(&b1, "\\", "\\\\"); // turn into C string 929 vadd(&compile, "-D"); 930 vadd(&compile, bprintf(&b, "GOROOT=\"%s\"", bstr(&b1))); 931 vadd(&compile, "-D"); 932 vadd(&compile, bprintf(&b, "GOVERSION=\"%s\"", goversion)); 933 vadd(&compile, "-D"); 934 vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm)); 935 vadd(&compile, "-D"); 936 vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386)); 937 vadd(&compile, "-D"); 938 vadd(&compile, bprintf(&b, "GO_EXTLINK_ENABLED=\"%s\"", goextlinkenabled)); 939 } 940 941 // gc/lex.c records the GOEXPERIMENT setting used during the build. 942 if(streq(name, "lex.c")) { 943 xgetenv(&b, "GOEXPERIMENT"); 944 vadd(&compile, "-D"); 945 vadd(&compile, bprintf(&b1, "GOEXPERIMENT=\"%s\"", bstr(&b))); 946 } 947 } else { 948 // Supporting files for a Go package. 949 if(hassuffix(files.p[i], ".s")) 950 vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar)); 951 else { 952 vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar)); 953 vadd(&compile, "-F"); 954 vadd(&compile, "-V"); 955 vadd(&compile, "-w"); 956 } 957 vadd(&compile, "-I"); 958 vadd(&compile, workdir); 959 vadd(&compile, "-I"); 960 vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch)); 961 vadd(&compile, "-D"); 962 vadd(&compile, bprintf(&b, "GOOS_%s", goos)); 963 vadd(&compile, "-D"); 964 vadd(&compile, bprintf(&b, "GOARCH_%s", goarch)); 965 } 966 967 bpathf(&b, "%s/%s", workdir, lastelem(files.p[i])); 968 doclean = 1; 969 if(!isgo && streq(gohostos, "darwin")) { 970 // To debug C programs on OS X, it is not enough to say -ggdb 971 // on the command line. You have to leave the object files 972 // lying around too. Leave them in pkg/obj/, which does not 973 // get removed when this tool exits. 974 bpathf(&b1, "%s/pkg/obj/%s", goroot, dir); 975 xmkdirall(bstr(&b1)); 976 bpathf(&b, "%s/%s", bstr(&b1), lastelem(files.p[i])); 977 doclean = 0; 978 } 979 980 // Change the last character of the output file (which was c or s). 981 if(streq(gohostos, "plan9")) 982 b.p[b.len-1] = gohostchar[0]; 983 else 984 b.p[b.len-1] = 'o'; 985 vadd(&compile, "-o"); 986 vadd(&compile, bstr(&b)); 987 vadd(&compile, files.p[i]); 988 bgrunv(bstr(&path), CheckExit, &compile); 989 990 vadd(&link, bstr(&b)); 991 if(doclean) 992 vadd(&clean, bstr(&b)); 993 } 994 bgwait(); 995 996 if(isgo) { 997 // The last loop was compiling individual files. 998 // Hand the Go files to the compiler en masse. 999 vreset(&compile); 1000 vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar)); 1001 1002 bpathf(&b, "%s/_go_.%s", workdir, gochar); 1003 vadd(&compile, "-o"); 1004 vadd(&compile, bstr(&b)); 1005 vadd(&clean, bstr(&b)); 1006 vadd(&link, bstr(&b)); 1007 1008 vadd(&compile, "-p"); 1009 if(hasprefix(dir, "pkg/")) 1010 vadd(&compile, dir+4); 1011 else 1012 vadd(&compile, "main"); 1013 1014 if(streq(dir, "pkg/runtime")) 1015 vadd(&compile, "-+"); 1016 1017 vcopy(&compile, go.p, go.len); 1018 1019 runv(nil, bstr(&path), CheckExit, &compile); 1020 } 1021 1022 if(!islib && !isgo) { 1023 // C binaries need the libraries explicitly, and -lm. 1024 vcopy(&link, lib.p, lib.len); 1025 if(!streq(gohostos, "plan9")) 1026 vadd(&link, "-lm"); 1027 } 1028 1029 // Remove target before writing it. 1030 xremove(link.p[targ]); 1031 1032 runv(nil, nil, CheckExit, &link); 1033 1034 nobuild: 1035 // In package runtime, we install runtime.h and cgocall.h too, 1036 // for use by cgo compilation. 1037 if(streq(dir, "pkg/runtime")) { 1038 copy(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch), 1039 bpathf(&b1, "%s/src/pkg/runtime/cgocall.h", goroot), 0); 1040 copy(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch), 1041 bpathf(&b1, "%s/src/pkg/runtime/runtime.h", goroot), 0); 1042 } 1043 1044 1045 out: 1046 for(i=0; i<clean.len; i++) 1047 xremove(clean.p[i]); 1048 1049 bfree(&b); 1050 bfree(&b1); 1051 bfree(&path); 1052 vfree(&compile); 1053 vfree(&files); 1054 vfree(&link); 1055 vfree(&go); 1056 vfree(&missing); 1057 vfree(&clean); 1058 vfree(&lib); 1059 vfree(&extra); 1060 } 1061 1062 // matchfield reports whether the field matches this build. 1063 static bool 1064 matchfield(char *f) 1065 { 1066 char *p; 1067 bool res; 1068 1069 p = xstrrchr(f, ','); 1070 if(p == nil) 1071 return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1"); 1072 *p = 0; 1073 res = matchfield(f) && matchfield(p+1); 1074 *p = ','; 1075 return res; 1076 } 1077 1078 // shouldbuild reports whether we should build this file. 1079 // It applies the same rules that are used with context tags 1080 // in package go/build, except that the GOOS and GOARCH 1081 // can appear anywhere in the file name, not just after _. 1082 // In particular, they can be the entire file name (like windows.c). 1083 // We also allow the special tag cmd_go_bootstrap. 1084 // See ../go/bootstrap.go and package go/build. 1085 static bool 1086 shouldbuild(char *file, char *dir) 1087 { 1088 char *name, *p; 1089 int i, j, ret; 1090 Buf b; 1091 Vec lines, fields; 1092 1093 // On Plan 9, most of the libraries are already present. 1094 // The main exception is libmach which has been modified 1095 // in various places to support Go object files. 1096 if(streq(gohostos, "plan9")) { 1097 if(streq(dir, "lib9")) { 1098 name = lastelem(file); 1099 if(streq(name, "goos.c") || streq(name, "flag.c")) 1100 return 1; 1101 if(!contains(name, "plan9")) 1102 return 0; 1103 } 1104 if(streq(dir, "libbio")) 1105 return 0; 1106 } 1107 1108 // Check file name for GOOS or GOARCH. 1109 name = lastelem(file); 1110 for(i=0; i<nelem(okgoos); i++) 1111 if(contains(name, okgoos[i]) && !streq(okgoos[i], goos)) 1112 return 0; 1113 for(i=0; i<nelem(okgoarch); i++) 1114 if(contains(name, okgoarch[i]) && !streq(okgoarch[i], goarch)) 1115 return 0; 1116 1117 // Omit test files. 1118 if(contains(name, "_test")) 1119 return 0; 1120 1121 // cmd/go/doc.go has a giant /* */ comment before 1122 // it gets to the important detail that it is not part of 1123 // package main. We don't parse those comments, 1124 // so special case that file. 1125 if(hassuffix(file, "cmd/go/doc.go") || hassuffix(file, "cmd\\go\\doc.go")) 1126 return 0; 1127 if(hassuffix(file, "cmd/cgo/doc.go") || hassuffix(file, "cmd\\cgo\\doc.go")) 1128 return 0; 1129 1130 // Check file contents for // +build lines. 1131 binit(&b); 1132 vinit(&lines); 1133 vinit(&fields); 1134 1135 ret = 1; 1136 readfile(&b, file); 1137 splitlines(&lines, bstr(&b)); 1138 for(i=0; i<lines.len; i++) { 1139 p = lines.p[i]; 1140 while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') 1141 p++; 1142 if(*p == '\0') 1143 continue; 1144 if(contains(p, "package documentation")) { 1145 ret = 0; 1146 goto out; 1147 } 1148 if(contains(p, "package main") && !streq(dir, "cmd/go") && !streq(dir, "cmd/cgo")) { 1149 ret = 0; 1150 goto out; 1151 } 1152 if(!hasprefix(p, "//")) 1153 break; 1154 if(!contains(p, "+build")) 1155 continue; 1156 splitfields(&fields, lines.p[i]); 1157 if(fields.len < 2 || !streq(fields.p[1], "+build")) 1158 continue; 1159 for(j=2; j<fields.len; j++) { 1160 p = fields.p[j]; 1161 if((*p == '!' && !matchfield(p+1)) || matchfield(p)) 1162 goto fieldmatch; 1163 } 1164 ret = 0; 1165 goto out; 1166 fieldmatch:; 1167 } 1168 1169 out: 1170 bfree(&b); 1171 vfree(&lines); 1172 vfree(&fields); 1173 1174 return ret; 1175 } 1176 1177 // copy copies the file src to dst, via memory (so only good for small files). 1178 static void 1179 copy(char *dst, char *src, int exec) 1180 { 1181 Buf b; 1182 1183 if(vflag > 1) 1184 errprintf("cp %s %s\n", src, dst); 1185 1186 binit(&b); 1187 readfile(&b, src); 1188 writefile(&b, dst, exec); 1189 bfree(&b); 1190 } 1191 1192 // buildorder records the order of builds for the 'go bootstrap' command. 1193 static char *buildorder[] = { 1194 "lib9", 1195 "libbio", 1196 "libmach", 1197 1198 "misc/pprof", 1199 1200 "cmd/addr2line", 1201 "cmd/cov", 1202 "cmd/nm", 1203 "cmd/objdump", 1204 "cmd/pack", 1205 "cmd/prof", 1206 1207 "cmd/cc", // must be before c 1208 "cmd/gc", // must be before g 1209 "cmd/%sl", // must be before a, c, g 1210 "cmd/%sa", 1211 "cmd/%sc", 1212 "cmd/%sg", 1213 1214 // The dependency order here was copied from a buildscript 1215 // back when there were build scripts. Will have to 1216 // be maintained by hand, but shouldn't change very 1217 // often. 1218 "pkg/runtime", 1219 "pkg/errors", 1220 "pkg/sync/atomic", 1221 "pkg/sync", 1222 "pkg/io", 1223 "pkg/unicode", 1224 "pkg/unicode/utf8", 1225 "pkg/unicode/utf16", 1226 "pkg/bytes", 1227 "pkg/math", 1228 "pkg/strings", 1229 "pkg/strconv", 1230 "pkg/bufio", 1231 "pkg/sort", 1232 "pkg/container/heap", 1233 "pkg/encoding/base64", 1234 "pkg/syscall", 1235 "pkg/time", 1236 "pkg/os", 1237 "pkg/reflect", 1238 "pkg/fmt", 1239 "pkg/encoding/json", 1240 "pkg/flag", 1241 "pkg/path/filepath", 1242 "pkg/path", 1243 "pkg/io/ioutil", 1244 "pkg/log", 1245 "pkg/regexp/syntax", 1246 "pkg/regexp", 1247 "pkg/go/token", 1248 "pkg/go/scanner", 1249 "pkg/go/ast", 1250 "pkg/go/parser", 1251 "pkg/os/exec", 1252 "pkg/os/signal", 1253 "pkg/net/url", 1254 "pkg/text/template/parse", 1255 "pkg/text/template", 1256 "pkg/go/doc", 1257 "pkg/go/build", 1258 "cmd/go", 1259 }; 1260 1261 // cleantab records the directories to clean in 'go clean'. 1262 // It is bigger than the buildorder because we clean all the 1263 // compilers but build only the $GOARCH ones. 1264 static char *cleantab[] = { 1265 "cmd/5a", 1266 "cmd/5c", 1267 "cmd/5g", 1268 "cmd/5l", 1269 "cmd/6a", 1270 "cmd/6c", 1271 "cmd/6g", 1272 "cmd/6l", 1273 "cmd/8a", 1274 "cmd/8c", 1275 "cmd/8g", 1276 "cmd/8l", 1277 "cmd/addr2line", 1278 "cmd/cc", 1279 "cmd/cov", 1280 "cmd/gc", 1281 "cmd/go", 1282 "cmd/nm", 1283 "cmd/objdump", 1284 "cmd/pack", 1285 "cmd/prof", 1286 "lib9", 1287 "libbio", 1288 "libmach", 1289 "pkg/bufio", 1290 "pkg/bytes", 1291 "pkg/container/heap", 1292 "pkg/encoding/base64", 1293 "pkg/encoding/json", 1294 "pkg/errors", 1295 "pkg/flag", 1296 "pkg/fmt", 1297 "pkg/go/ast", 1298 "pkg/go/build", 1299 "pkg/go/doc", 1300 "pkg/go/parser", 1301 "pkg/go/scanner", 1302 "pkg/go/token", 1303 "pkg/io", 1304 "pkg/io/ioutil", 1305 "pkg/log", 1306 "pkg/math", 1307 "pkg/net/url", 1308 "pkg/os", 1309 "pkg/os/exec", 1310 "pkg/path", 1311 "pkg/path/filepath", 1312 "pkg/reflect", 1313 "pkg/regexp", 1314 "pkg/regexp/syntax", 1315 "pkg/runtime", 1316 "pkg/sort", 1317 "pkg/strconv", 1318 "pkg/strings", 1319 "pkg/sync", 1320 "pkg/sync/atomic", 1321 "pkg/syscall", 1322 "pkg/text/template", 1323 "pkg/text/template/parse", 1324 "pkg/time", 1325 "pkg/unicode", 1326 "pkg/unicode/utf16", 1327 "pkg/unicode/utf8", 1328 }; 1329 1330 static void 1331 clean(void) 1332 { 1333 int i, j, k; 1334 Buf b, path; 1335 Vec dir; 1336 1337 binit(&b); 1338 binit(&path); 1339 vinit(&dir); 1340 1341 for(i=0; i<nelem(cleantab); i++) { 1342 if((streq(cleantab[i], "cmd/cov") || streq(cleantab[i], "cmd/prof")) && !isdir(cleantab[i])) 1343 continue; 1344 bpathf(&path, "%s/src/%s", goroot, cleantab[i]); 1345 xreaddir(&dir, bstr(&path)); 1346 // Remove generated files. 1347 for(j=0; j<dir.len; j++) { 1348 for(k=0; k<nelem(gentab); k++) { 1349 if(hasprefix(dir.p[j], gentab[k].nameprefix)) 1350 xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j])); 1351 } 1352 } 1353 // Remove generated binary named for directory. 1354 if(hasprefix(cleantab[i], "cmd/")) 1355 xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4)); 1356 } 1357 1358 // remove src/pkg/runtime/z* unconditionally 1359 vreset(&dir); 1360 bpathf(&path, "%s/src/pkg/runtime", goroot); 1361 xreaddir(&dir, bstr(&path)); 1362 for(j=0; j<dir.len; j++) { 1363 if(hasprefix(dir.p[j], "z")) 1364 xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j])); 1365 } 1366 1367 if(rebuildall) { 1368 // Remove object tree. 1369 xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch)); 1370 1371 // Remove installed packages and tools. 1372 xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch)); 1373 xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch)); 1374 xremoveall(tooldir); 1375 1376 // Remove cached version info. 1377 xremove(bpathf(&b, "%s/VERSION.cache", goroot)); 1378 } 1379 1380 bfree(&b); 1381 bfree(&path); 1382 vfree(&dir); 1383 } 1384 1385 /* 1386 * command implementations 1387 */ 1388 1389 void 1390 usage(void) 1391 { 1392 xprintf("usage: go tool dist [command]\n" 1393 "Commands are:\n" 1394 "\n" 1395 "banner print installation banner\n" 1396 "bootstrap rebuild everything\n" 1397 "clean deletes all built files\n" 1398 "env [-p] print environment (-p: include $PATH)\n" 1399 "install [dir] install individual directory\n" 1400 "version print Go version\n" 1401 "\n" 1402 "All commands take -v flags to emit extra information.\n" 1403 ); 1404 xexit(2); 1405 } 1406 1407 // The env command prints the default environment. 1408 void 1409 cmdenv(int argc, char **argv) 1410 { 1411 bool pflag; 1412 char *sep; 1413 Buf b, b1; 1414 char *format; 1415 1416 binit(&b); 1417 binit(&b1); 1418 1419 format = "%s=\"%s\"\n"; 1420 pflag = 0; 1421 ARGBEGIN{ 1422 case '9': 1423 format = "%s='%s'\n"; 1424 break; 1425 case 'p': 1426 pflag = 1; 1427 break; 1428 case 'v': 1429 vflag++; 1430 break; 1431 case 'w': 1432 format = "set %s=%s\r\n"; 1433 break; 1434 default: 1435 usage(); 1436 }ARGEND 1437 1438 if(argc > 0) 1439 usage(); 1440 1441 xprintf(format, "GOROOT", goroot); 1442 xprintf(format, "GOBIN", gobin); 1443 xprintf(format, "GOARCH", goarch); 1444 xprintf(format, "GOOS", goos); 1445 xprintf(format, "GOHOSTARCH", gohostarch); 1446 xprintf(format, "GOHOSTOS", gohostos); 1447 xprintf(format, "GOTOOLDIR", tooldir); 1448 xprintf(format, "GOCHAR", gochar); 1449 if(streq(goarch, "arm")) 1450 xprintf(format, "GOARM", goarm); 1451 if(streq(goarch, "386")) 1452 xprintf(format, "GO386", go386); 1453 1454 if(pflag) { 1455 sep = ":"; 1456 if(streq(gohostos, "windows")) 1457 sep = ";"; 1458 xgetenv(&b, "PATH"); 1459 bprintf(&b1, "%s%s%s", gobin, sep, bstr(&b)); 1460 xprintf(format, "PATH", bstr(&b1)); 1461 } 1462 1463 bfree(&b); 1464 bfree(&b1); 1465 } 1466 1467 // The bootstrap command runs a build from scratch, 1468 // stopping at having installed the go_bootstrap command. 1469 void 1470 cmdbootstrap(int argc, char **argv) 1471 { 1472 int i; 1473 Buf b; 1474 char *oldgoos, *oldgoarch, *oldgochar; 1475 1476 binit(&b); 1477 1478 ARGBEGIN{ 1479 case 'a': 1480 rebuildall = 1; 1481 break; 1482 case 'v': 1483 vflag++; 1484 break; 1485 default: 1486 usage(); 1487 }ARGEND 1488 1489 if(argc > 0) 1490 usage(); 1491 1492 if(rebuildall) 1493 clean(); 1494 goversion = findgoversion(); 1495 setup(); 1496 1497 xsetenv("GOROOT", goroot); 1498 xsetenv("GOROOT_FINAL", goroot_final); 1499 1500 // For the main bootstrap, building for host os/arch. 1501 oldgoos = goos; 1502 oldgoarch = goarch; 1503 oldgochar = gochar; 1504 goos = gohostos; 1505 goarch = gohostarch; 1506 gochar = gohostchar; 1507 xsetenv("GOARCH", goarch); 1508 xsetenv("GOOS", goos); 1509 1510 for(i=0; i<nelem(buildorder); i++) { 1511 install(bprintf(&b, buildorder[i], gohostchar)); 1512 if(!streq(oldgochar, gohostchar) && xstrstr(buildorder[i], "%s")) 1513 install(bprintf(&b, buildorder[i], oldgochar)); 1514 } 1515 1516 goos = oldgoos; 1517 goarch = oldgoarch; 1518 gochar = oldgochar; 1519 xsetenv("GOARCH", goarch); 1520 xsetenv("GOOS", goos); 1521 1522 // Build pkg/runtime for actual goos/goarch too. 1523 if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) 1524 install("pkg/runtime"); 1525 1526 bfree(&b); 1527 } 1528 1529 static char* 1530 defaulttarg(void) 1531 { 1532 char *p; 1533 Buf pwd, src, real_src; 1534 1535 binit(&pwd); 1536 binit(&src); 1537 binit(&real_src); 1538 1539 // xgetwd might return a path with symlinks fully resolved, and if 1540 // there happens to be symlinks in goroot, then the hasprefix test 1541 // will never succeed. Instead, we use xrealwd to get a canonical 1542 // goroot/src before the comparison to avoid this problem. 1543 xgetwd(&pwd); 1544 p = btake(&pwd); 1545 bpathf(&src, "%s/src/", goroot); 1546 xrealwd(&real_src, bstr(&src)); 1547 if(!hasprefix(p, bstr(&real_src))) 1548 fatal("current directory %s is not under %s", p, bstr(&real_src)); 1549 p += real_src.len; 1550 // guard againt xrealwd return the directory without the trailing / 1551 if(*p == slash[0]) 1552 p++; 1553 1554 bfree(&pwd); 1555 bfree(&src); 1556 bfree(&real_src); 1557 1558 return p; 1559 } 1560 1561 // Install installs the list of packages named on the command line. 1562 void 1563 cmdinstall(int argc, char **argv) 1564 { 1565 int i; 1566 1567 ARGBEGIN{ 1568 case 'v': 1569 vflag++; 1570 break; 1571 default: 1572 usage(); 1573 }ARGEND 1574 1575 if(argc == 0) 1576 install(defaulttarg()); 1577 1578 for(i=0; i<argc; i++) 1579 install(argv[i]); 1580 } 1581 1582 // Clean deletes temporary objects. 1583 // Clean -i deletes the installed objects too. 1584 void 1585 cmdclean(int argc, char **argv) 1586 { 1587 ARGBEGIN{ 1588 case 'v': 1589 vflag++; 1590 break; 1591 default: 1592 usage(); 1593 }ARGEND 1594 1595 if(argc > 0) 1596 usage(); 1597 1598 clean(); 1599 } 1600 1601 // Banner prints the 'now you've installed Go' banner. 1602 void 1603 cmdbanner(int argc, char **argv) 1604 { 1605 char *pathsep, *pid, *ns; 1606 Buf b, b1, search, path; 1607 1608 ARGBEGIN{ 1609 case 'v': 1610 vflag++; 1611 break; 1612 default: 1613 usage(); 1614 }ARGEND 1615 1616 if(argc > 0) 1617 usage(); 1618 1619 binit(&b); 1620 binit(&b1); 1621 binit(&search); 1622 binit(&path); 1623 1624 xprintf("\n"); 1625 xprintf("---\n"); 1626 xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot); 1627 xprintf("Installed commands in %s\n", gobin); 1628 1629 if(streq(gohostos, "plan9")) { 1630 // Check that gobin is bound before /bin. 1631 readfile(&b, "#c/pid"); 1632 bsubst(&b, " ", ""); 1633 pid = btake(&b); 1634 bprintf(&b, "/proc/%s/ns", pid); 1635 ns = btake(&b); 1636 readfile(&b, ns); 1637 bprintf(&search, "bind -b %s /bin\n", gobin); 1638 if(xstrstr(bstr(&b), bstr(&search)) == nil) 1639 xprintf("*** You need to bind %s before /bin.\n", gobin); 1640 } else { 1641 // Check that gobin appears in $PATH. 1642 xgetenv(&b, "PATH"); 1643 pathsep = ":"; 1644 if(streq(gohostos, "windows")) 1645 pathsep = ";"; 1646 bprintf(&b1, "%s%s%s", pathsep, bstr(&b), pathsep); 1647 bprintf(&search, "%s%s%s", pathsep, gobin, pathsep); 1648 if(xstrstr(bstr(&b1), bstr(&search)) == nil) 1649 xprintf("*** You need to add %s to your PATH.\n", gobin); 1650 } 1651 1652 if(streq(gohostos, "darwin")) { 1653 if(isfile(bpathf(&path, "%s/cov", tooldir))) 1654 xprintf("\n" 1655 "On OS X the debuggers must be installed setgid procmod.\n" 1656 "Read and run ./sudo.bash to install the debuggers.\n"); 1657 } 1658 1659 if(!xsamefile(goroot_final, goroot)) { 1660 xprintf("\n" 1661 "The binaries expect %s to be copied or moved to %s\n", 1662 goroot, goroot_final); 1663 } 1664 1665 bfree(&b); 1666 bfree(&b1); 1667 bfree(&search); 1668 bfree(&path); 1669 } 1670 1671 // Version prints the Go version. 1672 void 1673 cmdversion(int argc, char **argv) 1674 { 1675 ARGBEGIN{ 1676 case 'v': 1677 vflag++; 1678 break; 1679 default: 1680 usage(); 1681 }ARGEND 1682 1683 if(argc > 0) 1684 usage(); 1685 1686 xprintf("%s\n", goversion); 1687 }