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