"sort"
"strings"
"sync"
+ "time"
"cmd/internal/bio"
"cmd/internal/goobj"
}
}
+// cleanTimeStamps resets the timestamps for the specified list of
+// existing files to the Unix epoch (1970-01-01 00:00:00 +0000 UTC).
+// We take this step in order to help preserve reproducible builds;
+// this seems to be primarily needed for external linking on on Darwin
+// with later versions of xcode, which (unfortunately) seem to want to
+// incorporate object file times into the final output file's build
+// ID. See issue 64947 for the unpleasant details.
+func cleanTimeStamps(files []string) {
+ epocht := time.Unix(0, 0)
+ for _, f := range files {
+ if err := os.Chtimes(f, epocht, epocht); err != nil {
+ Exitf("cannot chtimes %s: %v", f, err)
+ }
+ }
+}
+
// hostobjCopy creates a copy of the object files in hostobj in a
// temporary directory.
func (ctxt *Link) hostobjCopy() (paths []string) {
if ctxt.HeadType == objabi.Haix {
argv = append(argv, "-X64")
}
+ godotopath := filepath.Join(*flagTmpdir, "go.o")
+ cleanTimeStamps([]string{godotopath})
+ hostObjCopyPaths := ctxt.hostobjCopy()
+ cleanTimeStamps(hostObjCopyPaths)
+
argv = append(argv, *flagOutfile)
- argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
- argv = append(argv, ctxt.hostobjCopy()...)
+ argv = append(argv, godotopath)
+ argv = append(argv, hostObjCopyPaths...)
if ctxt.Debugvlog != 0 {
ctxt.Logf("archive: %s\n", strings.Join(argv, " "))
argv = append(argv, compressDWARF)
}
- argv = append(argv, filepath.Join(*flagTmpdir, "go.o"))
- argv = append(argv, ctxt.hostobjCopy()...)
+ hostObjCopyPaths := ctxt.hostobjCopy()
+ cleanTimeStamps(hostObjCopyPaths)
+ godotopath := filepath.Join(*flagTmpdir, "go.o")
+ cleanTimeStamps([]string{godotopath})
+
+ argv = append(argv, godotopath)
+ argv = append(argv, hostObjCopyPaths...)
if ctxt.HeadType == objabi.Haix {
// We want to have C files after Go files to remove
// trampolines csects made by ld.