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