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