[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: