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