github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/misc/cgo/testcarchive/carchive_test.go (about) 1 // Copyright 2016 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 package carchive_test 6 7 import ( 8 "bufio" 9 "bytes" 10 "debug/elf" 11 "fmt" 12 "io/ioutil" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "regexp" 17 "runtime" 18 "strings" 19 "syscall" 20 "testing" 21 "time" 22 "unicode" 23 ) 24 25 // Program to run. 26 var bin []string 27 28 // C compiler with args (from $(go env CC) $(go env GOGCCFLAGS)). 29 var cc []string 30 31 // An environment with GOPATH=$(pwd). 32 var gopathEnv []string 33 34 // ".exe" on Windows. 35 var exeSuffix string 36 37 var GOOS, GOARCH string 38 var libgodir string 39 40 func init() { 41 GOOS = goEnv("GOOS") 42 GOARCH = goEnv("GOARCH") 43 bin = cmdToRun("./testp") 44 45 ccOut := goEnv("CC") 46 cc = []string{string(ccOut)} 47 48 out := goEnv("GOGCCFLAGS") 49 quote := '\000' 50 start := 0 51 lastSpace := true 52 backslash := false 53 s := string(out) 54 for i, c := range s { 55 if quote == '\000' && unicode.IsSpace(c) { 56 if !lastSpace { 57 cc = append(cc, s[start:i]) 58 lastSpace = true 59 } 60 } else { 61 if lastSpace { 62 start = i 63 lastSpace = false 64 } 65 if quote == '\000' && !backslash && (c == '"' || c == '\'') { 66 quote = c 67 backslash = false 68 } else if !backslash && quote == c { 69 quote = '\000' 70 } else if (quote == '\000' || quote == '"') && !backslash && c == '\\' { 71 backslash = true 72 } else { 73 backslash = false 74 } 75 } 76 } 77 if !lastSpace { 78 cc = append(cc, s[start:]) 79 } 80 81 if GOOS == "darwin" { 82 // For Darwin/ARM. 83 // TODO(crawshaw): can we do better? 84 cc = append(cc, []string{"-framework", "CoreFoundation", "-framework", "Foundation"}...) 85 } 86 libgodir = GOOS + "_" + GOARCH 87 if runtime.Compiler == "gccgo" { 88 libgodir = "gccgo_" + libgodir + "_fPIC" 89 } else { 90 switch GOOS { 91 case "darwin": 92 if GOARCH == "arm" || GOARCH == "arm64" { 93 libgodir += "_shared" 94 } 95 case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris": 96 libgodir += "_shared" 97 } 98 } 99 cc = append(cc, "-I", filepath.Join("pkg", libgodir)) 100 101 // Build an environment with GOPATH=$(pwd) 102 env := os.Environ() 103 var n []string 104 for _, e := range env { 105 if !strings.HasPrefix(e, "GOPATH=") { 106 n = append(n, e) 107 } 108 } 109 dir, err := os.Getwd() 110 if err != nil { 111 fmt.Fprintln(os.Stderr, err) 112 os.Exit(2) 113 } 114 n = append(n, "GOPATH="+dir) 115 gopathEnv = n 116 117 if GOOS == "windows" { 118 exeSuffix = ".exe" 119 } 120 } 121 122 func goEnv(key string) string { 123 out, err := exec.Command("go", "env", key).Output() 124 if err != nil { 125 fmt.Fprintf(os.Stderr, "go env %s failed:\n%s\n", key, err) 126 if ee, ok := err.(*exec.ExitError); ok { 127 fmt.Fprintf(os.Stderr, "%s", ee.Stderr) 128 } 129 os.Exit(2) 130 } 131 return strings.TrimSpace(string(out)) 132 } 133 134 func cmdToRun(name string) []string { 135 execScript := "go_" + goEnv("GOOS") + "_" + goEnv("GOARCH") + "_exec" 136 executor, err := exec.LookPath(execScript) 137 if err != nil { 138 return []string{name} 139 } 140 return []string{executor, name} 141 } 142 143 func testInstall(t *testing.T, exe, libgoa, libgoh string, buildcmd ...string) { 144 t.Helper() 145 cmd := exec.Command(buildcmd[0], buildcmd[1:]...) 146 cmd.Env = gopathEnv 147 t.Log(buildcmd) 148 if out, err := cmd.CombinedOutput(); err != nil { 149 t.Logf("%s", out) 150 t.Fatal(err) 151 } 152 defer func() { 153 os.Remove(libgoa) 154 os.Remove(libgoh) 155 }() 156 157 ccArgs := append(cc, "-o", exe, "main.c") 158 if GOOS == "windows" { 159 ccArgs = append(ccArgs, "main_windows.c", libgoa, "-lntdll", "-lws2_32", "-lwinmm") 160 } else { 161 ccArgs = append(ccArgs, "main_unix.c", libgoa) 162 } 163 if runtime.Compiler == "gccgo" { 164 ccArgs = append(ccArgs, "-lgo") 165 } 166 t.Log(ccArgs) 167 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 168 t.Logf("%s", out) 169 t.Fatal(err) 170 } 171 defer os.Remove(exe) 172 173 binArgs := append(cmdToRun(exe), "arg1", "arg2") 174 cmd = exec.Command(binArgs[0], binArgs[1:]...) 175 if runtime.Compiler == "gccgo" { 176 cmd.Env = append(os.Environ(), "GCCGO=1") 177 } 178 if out, err := cmd.CombinedOutput(); err != nil { 179 t.Logf("%s", out) 180 t.Fatal(err) 181 } 182 183 checkLineComments(t, libgoh) 184 } 185 186 var badLineRegexp = regexp.MustCompile(`(?m)^#line [0-9]+ "/.*$`) 187 188 // checkLineComments checks that the export header generated by 189 // -buildmode=c-archive doesn't have any absolute paths in the #line 190 // comments. We don't want those paths because they are unhelpful for 191 // the user and make the files change based on details of the location 192 // of GOPATH. 193 func checkLineComments(t *testing.T, hdrname string) { 194 hdr, err := ioutil.ReadFile(hdrname) 195 if err != nil { 196 if !os.IsNotExist(err) { 197 t.Error(err) 198 } 199 return 200 } 201 if line := badLineRegexp.Find(hdr); line != nil { 202 t.Errorf("bad #line directive with absolute path in %s: %q", hdrname, line) 203 } 204 } 205 206 func TestInstall(t *testing.T) { 207 defer os.RemoveAll("pkg") 208 209 libgoa := "libgo.a" 210 if runtime.Compiler == "gccgo" { 211 libgoa = "liblibgo.a" 212 } 213 214 testInstall(t, "./testp1"+exeSuffix, 215 filepath.Join("pkg", libgodir, libgoa), 216 filepath.Join("pkg", libgodir, "libgo.h"), 217 "go", "install", "-i", "-buildmode=c-archive", "libgo") 218 219 // Test building libgo other than installing it. 220 // Header files are now present. 221 testInstall(t, "./testp2"+exeSuffix, "libgo.a", "libgo.h", 222 "go", "build", "-buildmode=c-archive", filepath.Join("src", "libgo", "libgo.go")) 223 224 testInstall(t, "./testp3"+exeSuffix, "libgo.a", "libgo.h", 225 "go", "build", "-buildmode=c-archive", "-o", "libgo.a", "libgo") 226 } 227 228 func TestEarlySignalHandler(t *testing.T) { 229 switch GOOS { 230 case "darwin": 231 switch GOARCH { 232 case "arm", "arm64": 233 t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH) 234 } 235 case "windows": 236 t.Skip("skipping signal test on Windows") 237 } 238 239 defer func() { 240 os.Remove("libgo2.a") 241 os.Remove("libgo2.h") 242 os.Remove("testp") 243 os.RemoveAll("pkg") 244 }() 245 246 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2") 247 cmd.Env = gopathEnv 248 if out, err := cmd.CombinedOutput(); err != nil { 249 t.Logf("%s", out) 250 t.Fatal(err) 251 } 252 checkLineComments(t, "libgo2.h") 253 254 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main2.c", "libgo2.a") 255 if runtime.Compiler == "gccgo" { 256 ccArgs = append(ccArgs, "-lgo") 257 } 258 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 259 t.Logf("%s", out) 260 t.Fatal(err) 261 } 262 263 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil { 264 t.Logf("%s", out) 265 t.Fatal(err) 266 } 267 } 268 269 func TestSignalForwarding(t *testing.T) { 270 checkSignalForwardingTest(t) 271 272 defer func() { 273 os.Remove("libgo2.a") 274 os.Remove("libgo2.h") 275 os.Remove("testp") 276 os.RemoveAll("pkg") 277 }() 278 279 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2") 280 cmd.Env = gopathEnv 281 if out, err := cmd.CombinedOutput(); err != nil { 282 t.Logf("%s", out) 283 t.Fatal(err) 284 } 285 checkLineComments(t, "libgo2.h") 286 287 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a") 288 if runtime.Compiler == "gccgo" { 289 ccArgs = append(ccArgs, "-lgo") 290 } 291 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 292 t.Logf("%s", out) 293 t.Fatal(err) 294 } 295 296 cmd = exec.Command(bin[0], append(bin[1:], "1")...) 297 298 out, err := cmd.CombinedOutput() 299 t.Logf("%s", out) 300 expectSignal(t, err, syscall.SIGSEGV) 301 302 // Test SIGPIPE forwarding 303 cmd = exec.Command(bin[0], append(bin[1:], "3")...) 304 305 out, err = cmd.CombinedOutput() 306 t.Logf("%s", out) 307 expectSignal(t, err, syscall.SIGPIPE) 308 } 309 310 func TestSignalForwardingExternal(t *testing.T) { 311 if GOOS == "freebsd" { 312 t.Skipf("skipping on %s/%s; signal always goes to the Go runtime", GOOS, GOARCH) 313 } 314 checkSignalForwardingTest(t) 315 316 defer func() { 317 os.Remove("libgo2.a") 318 os.Remove("libgo2.h") 319 os.Remove("testp") 320 os.RemoveAll("pkg") 321 }() 322 323 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo2.a", "libgo2") 324 cmd.Env = gopathEnv 325 if out, err := cmd.CombinedOutput(); err != nil { 326 t.Logf("%s", out) 327 t.Fatal(err) 328 } 329 checkLineComments(t, "libgo2.h") 330 331 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main5.c", "libgo2.a") 332 if runtime.Compiler == "gccgo" { 333 ccArgs = append(ccArgs, "-lgo") 334 } 335 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 336 t.Logf("%s", out) 337 t.Fatal(err) 338 } 339 340 // We want to send the process a signal and see if it dies. 341 // Normally the signal goes to the C thread, the Go signal 342 // handler picks it up, sees that it is running in a C thread, 343 // and the program dies. Unfortunately, occasionally the 344 // signal is delivered to a Go thread, which winds up 345 // discarding it because it was sent by another program and 346 // there is no Go handler for it. To avoid this, run the 347 // program several times in the hopes that it will eventually 348 // fail. 349 const tries = 20 350 for i := 0; i < tries; i++ { 351 cmd = exec.Command(bin[0], append(bin[1:], "2")...) 352 353 stderr, err := cmd.StderrPipe() 354 if err != nil { 355 t.Fatal(err) 356 } 357 defer stderr.Close() 358 359 r := bufio.NewReader(stderr) 360 361 err = cmd.Start() 362 363 if err != nil { 364 t.Fatal(err) 365 } 366 367 // Wait for trigger to ensure that the process is started. 368 ok, err := r.ReadString('\n') 369 370 // Verify trigger. 371 if err != nil || ok != "OK\n" { 372 t.Fatalf("Did not receive OK signal") 373 } 374 375 // Give the program a chance to enter the sleep function. 376 time.Sleep(time.Millisecond) 377 378 cmd.Process.Signal(syscall.SIGSEGV) 379 380 err = cmd.Wait() 381 382 if err == nil { 383 continue 384 } 385 386 if expectSignal(t, err, syscall.SIGSEGV) { 387 return 388 } 389 } 390 391 t.Errorf("program succeeded unexpectedly %d times", tries) 392 } 393 394 // checkSignalForwardingTest calls t.Skip if the SignalForwarding test 395 // doesn't work on this platform. 396 func checkSignalForwardingTest(t *testing.T) { 397 switch GOOS { 398 case "darwin": 399 switch GOARCH { 400 case "arm", "arm64": 401 t.Skipf("skipping on %s/%s; see https://golang.org/issue/13701", GOOS, GOARCH) 402 } 403 case "windows": 404 t.Skip("skipping signal test on Windows") 405 } 406 } 407 408 // expectSignal checks that err, the exit status of a test program, 409 // shows a failure due to a specific signal. Returns whether we found 410 // the expected signal. 411 func expectSignal(t *testing.T, err error, sig syscall.Signal) bool { 412 if err == nil { 413 t.Error("test program succeeded unexpectedly") 414 } else if ee, ok := err.(*exec.ExitError); !ok { 415 t.Errorf("error (%v) has type %T; expected exec.ExitError", err, err) 416 } else if ws, ok := ee.Sys().(syscall.WaitStatus); !ok { 417 t.Errorf("error.Sys (%v) has type %T; expected syscall.WaitStatus", ee.Sys(), ee.Sys()) 418 } else if !ws.Signaled() || ws.Signal() != sig { 419 t.Errorf("got %v; expected signal %v", ee, sig) 420 } else { 421 return true 422 } 423 return false 424 } 425 426 func TestOsSignal(t *testing.T) { 427 switch GOOS { 428 case "windows": 429 t.Skip("skipping signal test on Windows") 430 } 431 432 defer func() { 433 os.Remove("libgo3.a") 434 os.Remove("libgo3.h") 435 os.Remove("testp") 436 os.RemoveAll("pkg") 437 }() 438 439 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo3.a", "libgo3") 440 cmd.Env = gopathEnv 441 if out, err := cmd.CombinedOutput(); err != nil { 442 t.Logf("%s", out) 443 t.Fatal(err) 444 } 445 checkLineComments(t, "libgo3.h") 446 447 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main3.c", "libgo3.a") 448 if runtime.Compiler == "gccgo" { 449 ccArgs = append(ccArgs, "-lgo") 450 } 451 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 452 t.Logf("%s", out) 453 t.Fatal(err) 454 } 455 456 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil { 457 t.Logf("%s", out) 458 t.Fatal(err) 459 } 460 } 461 462 func TestSigaltstack(t *testing.T) { 463 switch GOOS { 464 case "windows": 465 t.Skip("skipping signal test on Windows") 466 } 467 468 defer func() { 469 os.Remove("libgo4.a") 470 os.Remove("libgo4.h") 471 os.Remove("testp") 472 os.RemoveAll("pkg") 473 }() 474 475 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo4.a", "libgo4") 476 cmd.Env = gopathEnv 477 if out, err := cmd.CombinedOutput(); err != nil { 478 t.Logf("%s", out) 479 t.Fatal(err) 480 } 481 checkLineComments(t, "libgo4.h") 482 483 ccArgs := append(cc, "-o", "testp"+exeSuffix, "main4.c", "libgo4.a") 484 if runtime.Compiler == "gccgo" { 485 ccArgs = append(ccArgs, "-lgo") 486 } 487 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 488 t.Logf("%s", out) 489 t.Fatal(err) 490 } 491 492 if out, err := exec.Command(bin[0], bin[1:]...).CombinedOutput(); err != nil { 493 t.Logf("%s", out) 494 t.Fatal(err) 495 } 496 } 497 498 const testar = `#!/usr/bin/env bash 499 while [[ $1 == -* ]] >/dev/null; do 500 shift 501 done 502 echo "testar" > $1 503 echo "testar" > PWD/testar.ran 504 ` 505 506 func TestExtar(t *testing.T) { 507 switch GOOS { 508 case "windows": 509 t.Skip("skipping signal test on Windows") 510 } 511 if runtime.Compiler == "gccgo" { 512 t.Skip("skipping -extar test when using gccgo") 513 } 514 515 defer func() { 516 os.Remove("libgo4.a") 517 os.Remove("libgo4.h") 518 os.Remove("testar") 519 os.Remove("testar.ran") 520 os.RemoveAll("pkg") 521 }() 522 523 os.Remove("testar") 524 dir, err := os.Getwd() 525 if err != nil { 526 t.Fatal(err) 527 } 528 s := strings.Replace(testar, "PWD", dir, 1) 529 if err := ioutil.WriteFile("testar", []byte(s), 0777); err != nil { 530 t.Fatal(err) 531 } 532 533 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-ldflags=-extar="+filepath.Join(dir, "testar"), "-o", "libgo4.a", "libgo4") 534 cmd.Env = gopathEnv 535 if out, err := cmd.CombinedOutput(); err != nil { 536 t.Logf("%s", out) 537 t.Fatal(err) 538 } 539 checkLineComments(t, "libgo4.h") 540 541 if _, err := os.Stat("testar.ran"); err != nil { 542 if os.IsNotExist(err) { 543 t.Error("testar does not exist after go build") 544 } else { 545 t.Errorf("error checking testar: %v", err) 546 } 547 } 548 } 549 550 func TestPIE(t *testing.T) { 551 switch GOOS { 552 case "windows", "darwin", "plan9": 553 t.Skipf("skipping PIE test on %s", GOOS) 554 } 555 556 defer func() { 557 os.Remove("testp" + exeSuffix) 558 os.RemoveAll("pkg") 559 }() 560 561 cmd := exec.Command("go", "install", "-i", "-buildmode=c-archive", "libgo") 562 cmd.Env = gopathEnv 563 if out, err := cmd.CombinedOutput(); err != nil { 564 t.Logf("%s", out) 565 t.Fatal(err) 566 } 567 568 libgoa := "libgo.a" 569 if runtime.Compiler == "gccgo" { 570 libgoa = "liblibgo.a" 571 } 572 573 ccArgs := append(cc, "-fPIE", "-pie", "-o", "testp"+exeSuffix, "main.c", "main_unix.c", filepath.Join("pkg", libgodir, libgoa)) 574 if runtime.Compiler == "gccgo" { 575 ccArgs = append(ccArgs, "-lgo") 576 } 577 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 578 t.Logf("%s", out) 579 t.Fatal(err) 580 } 581 582 binArgs := append(bin, "arg1", "arg2") 583 cmd = exec.Command(binArgs[0], binArgs[1:]...) 584 if runtime.Compiler == "gccgo" { 585 cmd.Env = append(os.Environ(), "GCCGO=1") 586 } 587 if out, err := cmd.CombinedOutput(); err != nil { 588 t.Logf("%s", out) 589 t.Fatal(err) 590 } 591 592 f, err := elf.Open("testp" + exeSuffix) 593 if err != nil { 594 t.Fatal("elf.Open failed: ", err) 595 } 596 defer f.Close() 597 if hasDynTag(t, f, elf.DT_TEXTREL) { 598 t.Errorf("%s has DT_TEXTREL flag", "testp"+exeSuffix) 599 } 600 } 601 602 func hasDynTag(t *testing.T, f *elf.File, tag elf.DynTag) bool { 603 ds := f.SectionByType(elf.SHT_DYNAMIC) 604 if ds == nil { 605 t.Error("no SHT_DYNAMIC section") 606 return false 607 } 608 d, err := ds.Data() 609 if err != nil { 610 t.Errorf("can't read SHT_DYNAMIC contents: %v", err) 611 return false 612 } 613 for len(d) > 0 { 614 var t elf.DynTag 615 switch f.Class { 616 case elf.ELFCLASS32: 617 t = elf.DynTag(f.ByteOrder.Uint32(d[:4])) 618 d = d[8:] 619 case elf.ELFCLASS64: 620 t = elf.DynTag(f.ByteOrder.Uint64(d[:8])) 621 d = d[16:] 622 } 623 if t == tag { 624 return true 625 } 626 } 627 return false 628 } 629 630 func TestSIGPROF(t *testing.T) { 631 switch GOOS { 632 case "windows", "plan9": 633 t.Skipf("skipping SIGPROF test on %s", GOOS) 634 case "darwin": 635 t.Skipf("skipping SIGPROF test on %s; see https://golang.org/issue/19320", GOOS) 636 } 637 638 t.Parallel() 639 640 defer func() { 641 os.Remove("testp6" + exeSuffix) 642 os.Remove("libgo6.a") 643 os.Remove("libgo6.h") 644 }() 645 646 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-o", "libgo6.a", "libgo6") 647 cmd.Env = gopathEnv 648 if out, err := cmd.CombinedOutput(); err != nil { 649 t.Logf("%s", out) 650 t.Fatal(err) 651 } 652 checkLineComments(t, "libgo6.h") 653 654 ccArgs := append(cc, "-o", "testp6"+exeSuffix, "main6.c", "libgo6.a") 655 if runtime.Compiler == "gccgo" { 656 ccArgs = append(ccArgs, "-lgo") 657 } 658 if out, err := exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput(); err != nil { 659 t.Logf("%s", out) 660 t.Fatal(err) 661 } 662 663 argv := cmdToRun("./testp6") 664 cmd = exec.Command(argv[0], argv[1:]...) 665 if out, err := cmd.CombinedOutput(); err != nil { 666 t.Logf("%s", out) 667 t.Fatal(err) 668 } 669 } 670 671 // TestCompileWithoutShared tests that if we compile code without the 672 // -shared option, we can put it into an archive. When we use the go 673 // tool with -buildmode=c-archive, it passes -shared to the compiler, 674 // so we override that. The go tool doesn't work this way, but Bazel 675 // will likely do it in the future. And it ought to work. This test 676 // was added because at one time it did not work on PPC GNU/Linux. 677 func TestCompileWithoutShared(t *testing.T) { 678 // For simplicity, reuse the signal forwarding test. 679 checkSignalForwardingTest(t) 680 681 defer func() { 682 os.Remove("libgo2.a") 683 os.Remove("libgo2.h") 684 }() 685 686 cmd := exec.Command("go", "build", "-buildmode=c-archive", "-gcflags=-shared=false", "-o", "libgo2.a", "libgo2") 687 cmd.Env = gopathEnv 688 t.Log(cmd.Args) 689 out, err := cmd.CombinedOutput() 690 t.Logf("%s", out) 691 if err != nil { 692 t.Fatal(err) 693 } 694 checkLineComments(t, "libgo2.h") 695 696 exe := "./testnoshared" + exeSuffix 697 698 // In some cases, -no-pie is needed here, but not accepted everywhere. First try 699 // if -no-pie is accepted. See #22126. 700 ccArgs := append(cc, "-o", exe, "-no-pie", "main5.c", "libgo2.a") 701 if runtime.Compiler == "gccgo" { 702 ccArgs = append(ccArgs, "-lgo") 703 } 704 t.Log(ccArgs) 705 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() 706 707 // If -no-pie unrecognized, try -nopie if this is possibly clang 708 if err != nil && bytes.Contains(out, []byte("unknown")) && !strings.Contains(cc[0], "gcc") { 709 ccArgs = append(cc, "-o", exe, "-nopie", "main5.c", "libgo2.a") 710 t.Log(ccArgs) 711 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() 712 } 713 714 // Don't use either -no-pie or -nopie 715 if err != nil && bytes.Contains(out, []byte("unrecognized")) { 716 ccArgs := append(cc, "-o", exe, "main5.c", "libgo2.a") 717 t.Log(ccArgs) 718 out, err = exec.Command(ccArgs[0], ccArgs[1:]...).CombinedOutput() 719 } 720 t.Logf("%s", out) 721 if err != nil { 722 t.Fatal(err) 723 } 724 defer os.Remove(exe) 725 726 binArgs := append(cmdToRun(exe), "3") 727 t.Log(binArgs) 728 out, err = exec.Command(binArgs[0], binArgs[1:]...).CombinedOutput() 729 t.Logf("%s", out) 730 expectSignal(t, err, syscall.SIGPIPE) 731 } 732 733 // Test that installing a second time recreates the header files. 734 func TestCachedInstall(t *testing.T) { 735 defer os.RemoveAll("pkg") 736 737 h1 := filepath.Join("pkg", libgodir, "libgo.h") 738 h2 := filepath.Join("pkg", libgodir, "p.h") 739 740 buildcmd := []string{"go", "install", "-i", "-buildmode=c-archive", "libgo"} 741 742 cmd := exec.Command(buildcmd[0], buildcmd[1:]...) 743 cmd.Env = gopathEnv 744 t.Log(buildcmd) 745 if out, err := cmd.CombinedOutput(); err != nil { 746 t.Logf("%s", out) 747 t.Fatal(err) 748 } 749 750 if _, err := os.Stat(h1); err != nil { 751 t.Errorf("libgo.h not installed: %v", err) 752 } 753 if _, err := os.Stat(h2); err != nil { 754 t.Errorf("p.h not installed: %v", err) 755 } 756 757 if err := os.Remove(h1); err != nil { 758 t.Fatal(err) 759 } 760 if err := os.Remove(h2); err != nil { 761 t.Fatal(err) 762 } 763 764 cmd = exec.Command(buildcmd[0], buildcmd[1:]...) 765 cmd.Env = gopathEnv 766 t.Log(buildcmd) 767 if out, err := cmd.CombinedOutput(); err != nil { 768 t.Logf("%s", out) 769 t.Fatal(err) 770 } 771 772 if _, err := os.Stat(h1); err != nil { 773 t.Errorf("libgo.h not installed in second run: %v", err) 774 } 775 if _, err := os.Stat(h2); err != nil { 776 t.Errorf("p.h not installed in second run: %v", err) 777 } 778 }