8
8
"bufio"
9
9
"bytes"
10
10
"container/heap"
11
+ "crypto/sha256"
11
12
"debug/elf"
12
13
"encoding/json"
13
14
"errors"
@@ -684,6 +685,7 @@ type Action struct {
684
685
Args []string // additional args for runProgram
685
686
686
687
triggers []* Action // inverse of deps
688
+ buildID string
687
689
688
690
// Generated files, directories.
689
691
Objdir string // directory for intermediate objects
@@ -1466,6 +1468,18 @@ func (b *Builder) build(a *Action) (err error) {
1466
1468
}
1467
1469
}
1468
1470
1471
+ // We want to keep the action ID available for consultation later,
1472
+ // but we'll append to it the SHA256 of the file (without this ID included).
1473
+ // We don't know the SHA256 yet, so make one up to find and replace
1474
+ // later. Becuase the action ID is a hash of the inputs to this built,
1475
+ // the chance of SHA256(actionID) occurring elsewhere in the result
1476
+ // of the build is essentially zero, at least in 2017.
1477
+ actionID := a .Package .Internal .BuildID
1478
+ if actionID == "" {
1479
+ return fmt .Errorf ("missing action ID" )
1480
+ }
1481
+ a .buildID = actionID + "." + fmt .Sprintf ("%x" , sha256 .Sum256 ([]byte (actionID )))
1482
+
1469
1483
var gofiles , cgofiles , objdirCgofiles , cfiles , sfiles , cxxfiles , objects , cgoObjects , pcCFLAGS , pcLDFLAGS []string
1470
1484
1471
1485
gofiles = append (gofiles , a .Package .GoFiles ... )
@@ -1682,6 +1696,10 @@ func (b *Builder) build(a *Action) (err error) {
1682
1696
}
1683
1697
}
1684
1698
1699
+ if err := b .updateBuildID (a , actionID , objpkg ); err != nil {
1700
+ return err
1701
+ }
1702
+
1685
1703
return nil
1686
1704
}
1687
1705
@@ -1699,11 +1717,65 @@ func (b *Builder) link(a *Action) (err error) {
1699
1717
}
1700
1718
}
1701
1719
1720
+ actionID := a .Package .Internal .BuildID
1721
+ if actionID == "" {
1722
+ return fmt .Errorf ("missing action ID" )
1723
+ }
1724
+ a .buildID = actionID + "." + fmt .Sprintf ("%x" , sha256 .Sum256 ([]byte (actionID )))
1725
+
1702
1726
objpkg := a .Objdir + "_pkg_.a"
1703
1727
if err := BuildToolchain .ld (b , a , a .Target , importcfg , objpkg ); err != nil {
1704
1728
return err
1705
1729
}
1706
1730
1731
+ if err := b .updateBuildID (a , actionID , a .Target ); err != nil {
1732
+ return err
1733
+ }
1734
+
1735
+ return nil
1736
+ }
1737
+
1738
+ func (b * Builder ) updateBuildID (a * Action , actionID , target string ) error {
1739
+ if cfg .BuildX || cfg .BuildN {
1740
+ b .Showcmd ("" , "%s # internal" , joinUnambiguously (str .StringList (base .Tool ("buildid" ), "-w" , target )))
1741
+ if cfg .BuildN {
1742
+ return nil
1743
+ }
1744
+ }
1745
+
1746
+ // Find occurrences of old ID and compute new content-based ID.
1747
+ r , err := os .Open (target )
1748
+ if err != nil {
1749
+ return err
1750
+ }
1751
+ matches , hash , err := buildid .FindAndHash (r , a .buildID , 0 )
1752
+ r .Close ()
1753
+ if err != nil {
1754
+ return err
1755
+ }
1756
+ newID := fmt .Sprintf ("%s.%x" , actionID , hash )
1757
+ if len (newID ) != len (a .buildID ) {
1758
+ return fmt .Errorf ("internal error: build ID length mismatch %d+1+%d != %d" , len (actionID ), len (hash )* 2 , len (a .buildID ))
1759
+ }
1760
+
1761
+ // Replace with new content-based ID.
1762
+ a .buildID = newID
1763
+ if len (matches ) == 0 {
1764
+ // Assume the user specified -buildid= to override what we were going to choose.
1765
+ return nil
1766
+ }
1767
+ w , err := os .OpenFile (target , os .O_WRONLY , 0 )
1768
+ if err != nil {
1769
+ return err
1770
+ }
1771
+ err = buildid .Rewrite (w , matches , newID )
1772
+ if err != nil {
1773
+ w .Close ()
1774
+ return err
1775
+ }
1776
+ if err := w .Close (); err != nil {
1777
+ return err
1778
+ }
1707
1779
return nil
1708
1780
}
1709
1781
@@ -2451,8 +2523,8 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg []byte, a
2451
2523
if cfg .BuildContext .InstallSuffix != "" {
2452
2524
gcargs = append (gcargs , "-installsuffix" , cfg .BuildContext .InstallSuffix )
2453
2525
}
2454
- if p . Internal . BuildID != "" {
2455
- gcargs = append (gcargs , "-buildid" , p . Internal . BuildID )
2526
+ if a . buildID != "" {
2527
+ gcargs = append (gcargs , "-buildid" , a . buildID )
2456
2528
}
2457
2529
platform := cfg .Goos + "/" + cfg .Goarch
2458
2530
if p .Internal .OmitDebug || platform == "nacl/amd64p32" || platform == "darwin/arm" || platform == "darwin/arm64" || cfg .Goos == "plan9" {
@@ -2758,7 +2830,7 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string)
2758
2830
// Store BuildID inside toolchain binaries as a unique identifier of the
2759
2831
// tool being run, for use by content-based staleness determination.
2760
2832
if root .Package .Goroot && strings .HasPrefix (root .Package .ImportPath , "cmd/" ) {
2761
- ldflags = append (ldflags , "-X=cmd/internal/objabi.buildID=" + root .Package . Internal . BuildID )
2833
+ ldflags = append (ldflags , "-X=cmd/internal/objabi.buildID=" + root .buildID )
2762
2834
}
2763
2835
2764
2836
// If the user has not specified the -extld option, then specify the
@@ -2772,8 +2844,8 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg, mainpkg string)
2772
2844
compiler = envList ("CC" , cfg .DefaultCC )
2773
2845
}
2774
2846
ldflags = append (ldflags , "-buildmode=" + ldBuildmode )
2775
- if root .Package . Internal . BuildID != "" {
2776
- ldflags = append (ldflags , "-buildid=" + root .Package . Internal . BuildID )
2847
+ if root .buildID != "" {
2848
+ ldflags = append (ldflags , "-buildid=" + root .buildID )
2777
2849
}
2778
2850
ldflags = append (ldflags , cfg .BuildLdflags ... )
2779
2851
ldflags = setextld (ldflags , compiler )
0 commit comments