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