Bug#856042: gnat: please use SOURCE_DATE_EPOCH for reproducible ALI timestamps
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
Reply to: