Opened 5 years ago

Closed 6 months ago

Last modified 4 months ago

#59672 closed enhancement (fixed)

Set SOURCE_DATE_EPOCH

Reported by: ryandesign (Ryan Carsten Schmidt) Owned by: jmroot (Joshua Root)
Priority: Normal Milestone: MacPorts 2.10.0
Component: base Version:
Keywords: haspatch Cc: kurthindenburg (Kurt Hindenburg), harens (Haren S), tenzap, mascguy (Christopher Nielsen), jmroot (Joshua Root)
Port:

Description

MacPorts base could set the SOURCE_DATE_EPOCH environment variable.

Change History (16)

comment:1 Changed 5 years ago by kurthindenburg (Kurt Hindenburg)

Cc: kurthindenburg added

I've been looking at this. is the goal to have base have reproducible builds? or that the ports should be reproducible builds?

If I understand who this would workl, it would be use SOURCE_DATE_EPOCH in place of the current time in the logs/etc to allow all builds to be the same. This would require another option somewhere to do this.

SOURCE_DATE_EPOCH could/would be set to the last commit change. SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)

comment:2 Changed 5 years ago by ryandesign (Ryan Carsten Schmidt)

As far as I know builds of base are already reproducible, at least insofar as we don't deliberately use the build date/time anywhere.

I intended this ticket to suggest that MacPorts could add SOURCE_DATE_EPOCH to the environment when it builds ports so that ports' build systems that make use of this variable will be more reproducible. (Per the link in the ticket description: "SOURCE_DATE_EPOCH is a standardised environment variable that distributions can set centrally and have build tools consume this in order to produce reproducible output.") When I filed this ticket, I had just encountered a port that had such build system and I had been unaware of this variable.

comment:3 Changed 4 years ago by ryandesign (Ryan Carsten Schmidt)

In the wordgrinder port I have implemented it this way:

post-extract {
    set latest 0
    fs-traverse i [list ${worksrcpath}] {
        if {[file isfile ${i}]} {
            set t [file mtime ${i}]
            if {${t} > ${latest}} {
                set latest ${t}
            }
        }
    }
    set fp [open $env(TMPDIR)/SOURCE_DATE_EPOCH w]
    puts -nonewline ${fp} ${latest}
    close ${fp}
}
pre-build {
    set fp [open $env(TMPDIR)/SOURCE_DATE_EPOCH r]
    set latest [read ${fp}]
    close ${fp}
    build.env-append \
                    SOURCE_DATE_EPOCH=${latest}
}

The value needs to be determined right after extraction so that it is not affected by any changes made in the patch or configure phases and it needs to be saved to disk between phases in case the user is running the phases independently.

Maybe something similar can be done in base. The base version should include error-checking code that skips setting the environment variable if the file doesn't exist. (Users might have existing work directories that don't have the file.)

Last edited 4 years ago by ryandesign (Ryan Carsten Schmidt) (previous) (diff)

comment:4 Changed 4 years ago by ryandesign (Ryan Carsten Schmidt)

The base version should also set the environment variable in all relevant phases (patch, configure, build, destroot). It should be stored in memory so that it only needs to be read from disk once. We might store it in a new option that portfiles could even override if needed.

comment:5 Changed 3 years ago by harens (Haren S)

Cc: harens added

comment:6 Changed 3 years ago by tenzap

@ryandesign, do you think setting this variable can be managed directly in the tool that calls the various phases of the portfile. This would make SOURCE_DATE_EPOCH available for every port ?

May I suggest to add the revision number of the port (the value in the Portfile) to the timestamp in SOURCE_DATE_EPOCH? This would be like adding a few seconds to it and permit to represent in SOURCE_DATE_EPOCH that the Portfile changed. This is sort of analogous to the way debian does it (Debian uses the timestamp of the debian/changelog file).

comment:7 Changed 3 years ago by tenzap

Cc: tenzap added

comment:8 Changed 2 years ago by mascguy (Christopher Nielsen)

Cc: mascguy added

comment:9 in reply to:  6 ; Changed 18 months ago by ryandesign (Ryan Carsten Schmidt)

Keywords: haspatch added

Replying to tenzap:

do you think setting this variable can be managed directly in the tool that calls the various phases of the portfile. This would make SOURCE_DATE_EPOCH available for every port ?

What "tool" do you mean? The phases are run by MacPorts base. I am proposing that MacPorts base should set SOURCE_DATE_EPOCH in all phases of all ports.

Haren has provided a PR implementing this:

https://github.com/macports/macports-base/pull/274

May I suggest to add the revision number of the port (the value in the Portfile) to the timestamp in SOURCE_DATE_EPOCH? This would be like adding a few seconds to it and permit to represent in SOURCE_DATE_EPOCH that the Portfile changed. This is sort of analogous to the way debian does it (Debian uses the timestamp of the debian/changelog file).

I don't know if that's a good idea. I don't see anything recommending doing that in the documentation link I posted at the top. I am not familiar with what Debian does or why it does it.

comment:10 Changed 18 months ago by tenzap

I didn't know which tool processes the Portfile, now I know it's macports-base. While reading the ticket again, I probably didn't understand well. Now my comment seems actually inaccurate since SOURCE_DATE_EPOCH is apparently set to the last commit date of a port.

comment:11 Changed 6 months ago by jmroot (Joshua Root)

Cc: jmroot added

Would there be any serious drawback to simply setting SOURCE_DATE_EPOCH to a fixed value, at least to start with? The only one I can think of is that users might be slightly confused if the recorded timestamps are visible somewhere.

To use it the way Debian does, we would need to determine the timestamp of the last change to the port's directory in the macports-ports repo. That's not hard when using a git repo, but we would have to somehow add that information to the ports trees we serve via rsync and http, maybe in a metadata file.

comment:12 in reply to:  9 Changed 6 months ago by jmroot (Joshua Root)

Replying to ryandesign:

Replying to tenzap:

May I suggest to add the revision number of the port (the value in the Portfile) to the timestamp in SOURCE_DATE_EPOCH? This would be like adding a few seconds to it and permit to represent in SOURCE_DATE_EPOCH that the Portfile changed. This is sort of analogous to the way debian does it (Debian uses the timestamp of the debian/changelog file).

I don't know if that's a good idea. I don't see anything recommending doing that in the documentation link I posted at the top. I am not familiar with what Debian does or why it does it.

Debian increments the value only in the case of a Binary Non-Maintainer Upload. We don't have the problem that that solves for them. The equivalent of a Portfile change normally results in a new entry in debian/changelog which has a new timestamp.

comment:13 Changed 6 months ago by jmroot (Joshua Root)

In 4b70be1e3cbb7adf3241f7f3049804e9f0bc40cd/macports-base (master):

Set SOURCE_DATE_EPOCH in the environment

Fixed value for now.

See: #59672

comment:14 Changed 6 months ago by jmroot (Joshua Root)

Owner: set to jmroot
Resolution: fixed
Status: newclosed

In 4dfabb9c0de9abfcbb4acf1ad68471b0a20983ab/macports-base (master):

Set SOURCE_DATE_EPOCH to when port was last changed

This is the timestamp of the last commit affecting the portdir if it is
in a git repo, otherwise the latest mtime of the files in the portdir.

Closes: #59672
Closes: https://github.com/macports/macports-base/pull/274

Co-authored-by: harens <12570877+harens@…>

comment:15 Changed 6 months ago by jmroot (Joshua Root)

Milestone: MacPorts Future

comment:16 Changed 4 months ago by jmroot (Joshua Root)

Milestone: MacPorts FutureMacPorts 2.10.0
Note: See TracTickets for help on using tickets.