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