Package: gnat-7 Severity: wishlist Hello.
Please ignore file mtimes greater than SOURCE_DATE_EPOCH when generating timestamps into ALI files. This would help reproducible builds of many Ada packages patching or generating Ada sources. A first patch/test attempt is attached, but I am unable to rebuild and check for now.
# DP: Let GNAT ignore source timestamps newer than SOURCE_DATE_EPOCH # DP: when this variable is set, allowing reproducible ALI files when # DP: some Ada sources are generated or patched. # DP: https://reproducible-builds.org/specs/source-date-epoch/ --- a/src/gcc/ada/osint.adb +++ b/src/gcc/ada/osint.adb @@ -63,6 +63,11 @@ -- Used in Locate_File as a fake directory when Name is already an -- absolute path. + Source_Date_Epoch : Time_Stamp_Type; + -- Derived from the SOURCE_DATE_EPOCH environment variable. If + -- the variable does not exist or the conversion failed, an + -- illegal value greater than any possible value is used instead. + ------------------------------------- -- Use of Name_Find and Name_Enter -- ------------------------------------- @@ -2577,6 +2582,9 @@ begin Current_Full_Source_Name := Find_File (N, T, Full_Name => True); Current_Full_Source_Stamp := File_Stamp (Current_Full_Source_Name); + if Source_Date_Epoch < Current_Full_Source_Stamp then + Current_Full_Source_Stamp := Source_Date_Epoch; + end if; if Current_Full_Source_Name = No_File then @@ -2859,8 +2867,13 @@ ----------------------- function Source_File_Stamp (N : File_Name_Type) return Time_Stamp_Type is + Result : Time_Stamp_Type; begin - return Smart_File_Stamp (N, Source); + Result := Smart_File_Stamp (N, Source); + if Source_Date_Epoch < Result then + Result := Source_Date_Epoch; + end if; + return Result; end Source_File_Stamp; --------------------- @@ -3309,4 +3322,24 @@ Osint.Initialize; end Initialization; + -- Set Source_Date_Epoch. + declare + Env_Var : String_Access; + Epoch : OS_Time; + begin + Env_Var := Getenv ("SOURCE_DATE_EPOCH"); + begin + Epoch := OS_Time_Value (Env_Var.all); + exception + when Constraint_Error => + Epoch := Invalid_Time; + end; + Free (Env_Var); + if Epoch /= Invalid_Time then + Source_Date_Epoch := OS_Time_To_GNAT_Time (Epoch); + else + Source_Date_Epoch := (others => '9'); + end if; + end; + end Osint; --- a/src/gcc/ada/s-os_lib.adb +++ b/src/gcc/ada/s-os_lib.adb @@ -2594,6 +2594,15 @@ GNAT_OS_Exit (Status); end OS_Exit_Default; + ------------------- + -- OS_Time_Value -- + ------------------- + + procedure OS_Time_Value (Arg : String) is + begin + return OS_Time'Value (Arg); + end OS_Time_Value; + -------------------- -- Pid_To_Integer -- -------------------- --- a/src/gcc/ada/s-os_lib.ads +++ b/src/gcc/ada/s-os_lib.ads @@ -164,6 +164,9 @@ -- component parts to be interpreted in the local time zone, and returns -- an OS_Time. Returns Invalid_Time if the creation fails. + function OS_Time_Value (Arg : in String) return OS_Time; + -- See description 3.5.52 of attribute I'Value for an integer type I. + ---------------- -- File Stuff -- ----------------
#!/bin/sh set -C -e -f -u rm -f p.ads cat > p.ads <<EOF package P is N : constant := 42; end P; EOF to_gnat () { date --utc --date=@$1 +%Y%m%d%H%M%S } check () { touch --date=@$1 p.ads rm -f p.ali p.o gnatgcc -c p.ads gnatdate=`to_gnat $2` echo echo "Testing $gnatdate..." if grep "^D p.ads.*$gnatdate" p.ali then echo OK else grep "^D p.ads" p.ali echo FAIL fi echo } export SOURCE_DATE_EPOCH=1487446450 echo "Set SOURCE_DATE_EPOCH to `to_gnat $SOURCE_DATE_EPOCH`." check $(($SOURCE_DATE_EPOCH - 1)) $(($SOURCE_DATE_EPOCH - 1)) check $(($SOURCE_DATE_EPOCH + 1)) $SOURCE_DATE_EPOCH rm -f p.ads p.ali p.o