@@ -867,6 +867,7 @@ def sdist(self, directory: Path) -> pathlib.Path:
867867 meson_dist_name = f'{ self ._meson_name } -{ self ._meson_version } '
868868 meson_dist_path = pathlib .Path (self ._build_dir , 'meson-dist' , f'{ meson_dist_name } .tar.gz' )
869869 sdist_path = pathlib .Path (directory , f'{ dist_name } .tar.gz' )
870+ pyproject_toml_mtime = 0
870871
871872 with tarfile .open (meson_dist_path , 'r:gz' ) as meson_dist , mesonpy ._util .create_targz (sdist_path ) as sdist :
872873 for member in meson_dist .getmembers ():
@@ -877,6 +878,9 @@ def sdist(self, directory: Path) -> pathlib.Path:
877878 stem = member .name .split ('/' , 1 )[1 ]
878879 member .name = '/' .join ((dist_name , stem ))
879880
881+ if stem == 'pyproject.toml' :
882+ pyproject_toml_mtime = member .mtime
883+
880884 # Reset owner and group to root:root. This mimics what
881885 # 'git archive' does and makes the sdist reproducible upon
882886 # being built by different users.
@@ -889,7 +893,23 @@ def sdist(self, directory: Path) -> pathlib.Path:
889893 member = tarfile .TarInfo (f'{ dist_name } /PKG-INFO' )
890894 member .uid = member .gid = 0
891895 member .uname = member .gname = 'root'
892- member .mtime = time .time ()
896+
897+ # Set the 'PKG-INFO' modification time to the modification time of
898+ # 'pyproject.toml' in the archive generated by 'meson dist'. In
899+ # turn this is the last commit time, unless touched by a dist
900+ # script. This makes the sdist reproducible upon being built at
901+ # different times, when dist scripts are not used, which should be
902+ # the majority of cases.
903+ #
904+ # Note that support for dynamic version in project metadata allows
905+ # the version to depend on the build time. Therefore, setting the
906+ # 'PKG-INFO' modification time to the 'pyproject.toml'
907+ # modification time can be seen as not strictly correct. However,
908+ # the sdist standard does not dictate which modification time to
909+ # use for 'PKG-INFO'. This choice allows to make the sdist
910+ # byte-for-byte reproducible in the most common case.
911+ member .mtime = pyproject_toml_mtime
912+
893913 metadata = bytes (self ._metadata .as_rfc822 ())
894914 member .size = len (metadata )
895915 sdist .addfile (member , io .BytesIO (metadata ))
0 commit comments