[polyml] 09/13: Make build reproducible

James Clarke jrtc27-guest at moszumanska.debian.org
Sat Mar 12 20:28:25 UTC 2016


This is an automated email from the git hooks/post-receive script.

jrtc27-guest pushed a commit to branch master
in repository polyml.

commit 66cb98da24589ad799c1bd3f3e756cd2bddb56c0
Author: James Clarke <jrtc27 at jrtc27.com>
Date:   Fri Mar 11 16:55:23 2016 +0000

    Make build reproducible
---
 debian/changelog                      |   4 +
 debian/patches/bss-ioarea.diff        | 281 ++++++++++++++++++++++++++++++++++
 debian/patches/series                 |   2 +
 debian/patches/source-date-epoch.diff | 252 ++++++++++++++++++++++++++++++
 4 files changed, 539 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index ea9baeb..ca8845b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,12 +1,16 @@
 polyml (5.6-3) UNRELEASED; urgency=low
 
   * Support for the Hurd
+  * Build is now reproducible
   * New patches:
     - alpha.diff: Add support for alpha
+    - bss-ioarea.diff: Export ioarea to bss section
     - m68k.diff: Add support for m68k
     - maxpathlen.diff: Remove all use of MAXPATHLEN
     - mips64.diff: Add support for mips64/mips64el
     - noexec-stack-gnu.diff: Mark stack as non-executable on all GNU systems
+    - source-date-epoch.diff: Use SOURCE_DATE_EPOCH instead of current time if
+    it is defined
     - x32.diff: Add support for x32
 
  -- James Clarke <jrtc27 at jrtc27.com>  Tue, 02 Feb 2016 21:15:49 +0000
diff --git a/debian/patches/bss-ioarea.diff b/debian/patches/bss-ioarea.diff
new file mode 100644
index 0000000..0dba99b
--- /dev/null
+++ b/debian/patches/bss-ioarea.diff
@@ -0,0 +1,281 @@
+Description: Export ioarea to bss section
+Author: James Clarke <jrtc27 at jrtc27.com>
+Forwarded: https://github.com/polyml/polyml/pull/31
+Applied-Upstream: https://github.com/polyml/polyml/commit/9f2cb26e5c91fc8cd59d1348961a4ded0ca1b1d3
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/libpolyml/elfexport.cpp
++++ b/libpolyml/elfexport.cpp
+@@ -340,9 +340,9 @@
+     PolyWord    *p;
+     ElfXX_Ehdr fhdr;
+     ElfXX_Shdr *sections = 0;
+-    unsigned numSections = 6 + 2*memTableEntries;
++    unsigned numSections = 6 + 2*memTableEntries - 1;
+     // The symbol table comes at the end.
+-    unsigned sect_symtab = sect_data + 2*memTableEntries + 2;
++    unsigned sect_symtab = sect_data + 2*memTableEntries + 2 - 1;
+     
+     unsigned i;
+ 
+@@ -485,6 +485,7 @@
+     // sections[sect_stringtable].sh_offset is set later
+     // sections[sect_stringtable].sh_size is set later
+ 
++    unsigned long bssName = makeStringTableEntry(".bss", &sectionStrings);
+     unsigned long dataName = makeStringTableEntry(".data", &sectionStrings);
+     unsigned long dataRelName = makeStringTableEntry(useRela ? ".rela.data" : ".rel.data", &sectionStrings);
+     unsigned long textName = makeStringTableEntry(".text", &sectionStrings);
+@@ -493,41 +494,52 @@
+     // Main data sections.  Each one has a relocation section.
+     for (i=0; i < memTableEntries; i++)
+     {
+-        unsigned s = sect_data + i*2;
+-        sections[s].sh_type = SHT_PROGBITS;
++        unsigned s = sect_data + i*2 - (i > ioMemEntry ? 1 : 0);
+         sections[s].sh_addralign = 8; // 8-byte alignment
+ 
+-        if (memTable[i].mtFlags & MTF_WRITEABLE)
++        if (i == ioMemEntry)
+         {
+-            // Mutable areas
+-            ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE)); // Executable areas can't be writable.
+-            sections[s].sh_name = dataName;
++            ASSERT(memTable[i].mtFlags & MTF_WRITEABLE);
++            ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE));
++            sections[s].sh_name = bssName;
++            sections[s].sh_type = SHT_NOBITS;
+             sections[s].sh_flags = SHF_WRITE | SHF_ALLOC;
+-            sections[s+1].sh_name = dataRelName; // Name of relocation section
+         }
+         else
+         {
+-            // Immutable areas are marked as executable.
+-            sections[s].sh_name = textName;
+-            sections[s].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+-            sections[s+1].sh_name = textRelName; // Name of relocation section
++            sections[s].sh_type = SHT_PROGBITS;
++            if (memTable[i].mtFlags & MTF_WRITEABLE)
++            {
++                // Mutable areas
++                ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE)); // Executable areas can't be writable.
++                sections[s].sh_name = dataName;
++                sections[s].sh_flags = SHF_WRITE | SHF_ALLOC;
++                sections[s+1].sh_name = dataRelName; // Name of relocation section
++            }
++            else
++            {
++                // Immutable areas are marked as executable.
++                sections[s].sh_name = textName;
++                sections[s].sh_flags = SHF_ALLOC | SHF_EXECINSTR;
++                sections[s+1].sh_name = textRelName; // Name of relocation section
++            }
++            // sections[s].sh_size is set later
++            // sections[s].sh_offset is set later.
++            // sections[s].sh_size is set later.
++
++            // Relocation section
++            sections[s+1].sh_type = useRela ? SHT_RELA : SHT_REL; // Contains relocation with/out explicit addends (ElfXX_Rel)
++            sections[s+1].sh_link = sect_symtab; // Index to symbol table
++            sections[s+1].sh_info = s; // Applies to the data section
++            sections[s+1].sh_addralign = sizeof(long); // Align to a word
++            sections[s+1].sh_entsize = useRela ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel);
++            // sections[s+1].sh_offset is set later.
++            // sections[s+1].sh_size is set later.
+         }
+-        // sections[s].sh_size is set later
+-        // sections[s].sh_offset is set later.
+-        // sections[s].sh_size is set later.
+-
+-        // Relocation section
+-        sections[s+1].sh_type = useRela ? SHT_RELA : SHT_REL; // Contains relocation with/out explicit addends (ElfXX_Rel)
+-        sections[s+1].sh_link = sect_symtab; // Index to symbol table
+-        sections[s+1].sh_info = s; // Applies to the data section
+-        sections[s+1].sh_addralign = sizeof(long); // Align to a word
+-        sections[s+1].sh_entsize = useRela ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel);
+-        // sections[s+1].sh_offset is set later.
+-        // sections[s+1].sh_size is set later.
+     }
+ 
+     // Table data - Poly tables that describe the memory layout.
+-    unsigned sect_table_data = sect_data+2*memTableEntries;
++    unsigned sect_table_data = sect_data + 2*memTableEntries - 1;
+ 
+     sections[sect_table_data].sh_name = dataName;
+     sections[sect_table_data].sh_type = SHT_PROGBITS;
+@@ -561,12 +573,13 @@
+     // Create symbols for the address areas.  AreaToSym assumes these come first.
+     for (i = 0; i < memTableEntries; i++)
+     {
++        unsigned s = sect_data + i*2 - (i > ioMemEntry ? 1 : 0);
+         if (i == ioMemEntry)
+-            writeSymbol("ioarea", 0, 0, STB_LOCAL, STT_OBJECT, sect_data+i*2);
++            writeSymbol("ioarea", 0, 0, STB_LOCAL, STT_OBJECT, s);
+         else {
+             char buff[50];
+             sprintf(buff, "area%1u", i);
+-            writeSymbol(buff, 0, 0, STB_LOCAL, STT_OBJECT, sect_data+i*2);
++            writeSymbol(buff, 0, 0, STB_LOCAL, STT_OBJECT, s);
+         }
+     }
+ 
+@@ -575,6 +588,7 @@
+     {
+         if (i != ioMemEntry)
+         {
++            unsigned s = sect_data + i*2 - (i > ioMemEntry ? 1 : 0);
+             char buff[50];
+             // Write the names of the functions as local symbols.  This isn't necessary
+             // but it makes debugging easier since the function names appear in gdb.
+@@ -591,7 +605,7 @@
+                     // Copy as much of the name as will fit and ignore any extra.
+                     // Do we need to worry about duplicates?
+                     (void)Poly_string_to_C(*name, buff, sizeof(buff));
+-                    writeSymbol(buff, ((char*)p - start), 0, STB_LOCAL, STT_OBJECT, sect_data+i*2);
++                    writeSymbol(buff, ((char*)p - start), 0, STB_LOCAL, STT_OBJECT, s);
+                 }
+                 p += length;
+             }
+@@ -610,12 +624,12 @@
+ 
+     for (i = 0; i < memTableEntries; i++)
+     {
+-        unsigned relocSection = sect_data+i*2+1;
+-        alignFile(sections[relocSection].sh_addralign);
+-        sections[relocSection].sh_offset = ftell(exportFile);
+-        relocationCount = 0;
+         if (i != ioMemEntry) // Don't relocate the IO area
+         {
++            unsigned relocSection = sect_data + i*2 + 1 - (i > ioMemEntry ? 1 : 0);
++            alignFile(sections[relocSection].sh_addralign);
++            sections[relocSection].sh_offset = ftell(exportFile);
++            relocationCount = 0;
+             // Create the relocation table and turn all addresses into offsets.
+             char *start = (char*)memTable[i].mtAddr;
+             char *end = start + memTable[i].mtLength;
+@@ -631,9 +645,9 @@
+                 relocateObject(obj);
+                 p += length;
+             }
++            sections[relocSection].sh_size =
++                relocationCount * (useRela ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel));
+         }
+-        sections[relocSection].sh_size =
+-            relocationCount * (useRela ? sizeof(ElfXX_Rela) : sizeof(ElfXX_Rel));
+     }
+ 
+     // Relocations for "exports" and "memTable";
+@@ -671,11 +685,15 @@
+     // Now the binary data.
+     for (i = 0; i < memTableEntries; i++)
+     {
+-        unsigned dataSection = sect_data+i*2;
+-        alignFile(sections[dataSection].sh_addralign);
+-        sections[dataSection].sh_offset = ftell(exportFile);
++        unsigned dataSection = sect_data + i*2 - (i > ioMemEntry ? 1 : 0);
+         sections[dataSection].sh_size = memTable[i].mtLength;
+-        fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile);
++
++        if (i != ioMemEntry)
++        {
++            alignFile(sections[dataSection].sh_addralign);
++            sections[dataSection].sh_offset = ftell(exportFile);
++            fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile);
++        }
+     }
+ 
+     exportDescription exports;
+--- a/libpolyml/machoexport.cpp
++++ b/libpolyml/machoexport.cpp
+@@ -334,7 +334,15 @@
+     {
+         memset(&(sections[i]), 0, sectionSize);
+ 
+-        if (memTable[i].mtFlags & MTF_WRITEABLE)
++        if (i == ioMemEntry)
++        {
++            ASSERT(memTable[i].mtFlags & MTF_WRITEABLE);
++            ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE));
++            sprintf(sections[i].sectname, "__bss");
++            sprintf(sections[i].segname, "__DATA");
++            sections[i].flags = S_ZEROFILL;
++        }
++        else if (memTable[i].mtFlags & MTF_WRITEABLE)
+         {
+             // Mutable areas
+             ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE)); // Executable areas can't be writable.
+@@ -433,10 +441,10 @@
+     // Create and write out the relocations.
+     for (i = 0; i < memTableEntries; i++)
+     {
+-        sections[i].reloff = ftell(exportFile);
+-        relocationCount = 0;
+         if (i != ioMemEntry) // Don't relocate the IO area
+         {
++            sections[i].reloff = ftell(exportFile);
++            relocationCount = 0;
+             // Create the relocation table and turn all addresses into offsets.
+             char *start = (char*)memTable[i].mtAddr;
+             char *end = start + memTable[i].mtLength;
+@@ -450,8 +458,8 @@
+                 relocateObject(obj);
+                 p += length;
+             }
++            sections[i].nreloc = relocationCount;
+         }
+-        sections[i].nreloc = relocationCount;
+     }
+ 
+     // Additional relocations for the descriptors.
+@@ -512,9 +520,16 @@
+     // Now the binary data.
+     for (i = 0; i < memTableEntries; i++)
+     {
+-        alignFile(4);
+-        sections[i].offset = ftell(exportFile);
+-        fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile);
++        if (i == ioMemEntry)
++        {
++            sections[i].offset = 0;
++        }
++        else
++        {
++            alignFile(4);
++            sections[i].offset = ftell(exportFile);
++            fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile);
++        }
+     }
+     // Rewind to rewrite the headers with the actual offsets.
+     rewind(exportFile);
+--- a/libpolyml/pecoffexport.cpp
++++ b/libpolyml/pecoffexport.cpp
+@@ -208,7 +208,14 @@
+         sections[i].SizeOfRawData = (DWORD)memTable[i].mtLength;
+         sections[i].Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_ALIGN_8BYTES;
+ 
+-        if (memTable[i].mtFlags & MTF_WRITEABLE)
++        if (i == ioMemEntry)
++        {
++            ASSERT(memTable[i].mtFlags & MTF_WRITEABLE);
++            ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE));
++            strcpy((char*)sections[i].Name, ".bss");
++            sections[i].Characteristics |= IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_UNINITIALIZED_DATA;
++        }
++        else if (memTable[i].mtFlags & MTF_WRITEABLE)
+         {
+             // Mutable data
+             ASSERT(!(memTable[i].mtFlags & MTF_EXECUTABLE)); // Executable areas can't be writable.
+@@ -313,8 +320,11 @@
+     // Now the binary data.
+     for (i = 0; i < memTableEntries; i++)
+     {
+-        sections[i].PointerToRawData = ftell(exportFile);
+-        fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile);
++        if (i != ioMemEntry)
++        {
++            sections[i].PointerToRawData = ftell(exportFile);
++            fwrite(memTable[i].mtAddr, 1, memTable[i].mtLength, exportFile);
++        }
+     }
+ 
+     sections[memTableEntries].PointerToRawData = ftell(exportFile);
diff --git a/debian/patches/series b/debian/patches/series
index b396ee3..74c0ca5 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -16,3 +16,5 @@ mips64.diff
 x32.diff
 maxpathlen.diff
 noexec-stack-gnu.diff
+source-date-epoch.diff
+bss-ioarea.diff
diff --git a/debian/patches/source-date-epoch.diff b/debian/patches/source-date-epoch.diff
new file mode 100644
index 0000000..276b70d
--- /dev/null
+++ b/debian/patches/source-date-epoch.diff
@@ -0,0 +1,252 @@
+Description: Use SOURCE_DATE_EPOCH instead of current time if it is defined
+Author: James Clarke <jrtc27 at jrtc27.com>
+Forwarded: https://github.com/polyml/polyml/pull/31
+Applied-Upstream: https://github.com/polyml/polyml/commit/9f2cb26e5c91fc8cd59d1348961a4ded0ca1b1d3
+---
+This patch header follows DEP-3: http://dep.debian.net/deps/dep3/
+--- a/basis/FinalPolyML.sml
++++ b/basis/FinalPolyML.sml
+@@ -833,10 +833,6 @@
+     (* Time stamps. *)
+     type timeStamp = Time.time;
+     val firstTimeStamp : timeStamp = Time.zeroTime;
+-    (* Get the current time. *)
+-    val newTimeStamp : unit -> timeStamp = Time.now
+-    (* Get the date of a file. *)
+-    val fileTimeStamp : string -> timeStamp = OS.FileSys.modTime
+     
+     local
+         open ProtectedTable
+@@ -862,6 +858,27 @@
+     (* Main make function *)
+     fun make (targetName: string) : unit =
+     let
++        local
++            val sourceDateEpochEnv : string option = OS.Process.getEnv "SOURCE_DATE_EPOCH";
++        in
++            val sourceDateEpoch : timeStamp option =
++                case sourceDateEpochEnv of
++                     NONE => NONE
++                   | SOME s =>
++                       (case Int.fromString s of
++                             NONE => NONE
++                           | SOME t => SOME(Time.fromSeconds t) handle Time.Time => NONE)
++        end;
++
++        (* Get the current time. *)
++        val newTimeStamp : unit -> timeStamp = case sourceDateEpoch of
++                                                    NONE => Time.now
++                                                  | SOME t => fn _ => t;
++        (* Get the date of a file. *)
++        val fileTimeStamp : string -> timeStamp = case sourceDateEpoch of
++                                                    NONE => OS.FileSys.modTime
++                                                  | SOME t => fn _ => t;
++
+         (* This serves two purposes. It provides a list of objects which have been
+            re-made to prevent them being made more than once, and it also prevents
+            circular dependencies from causing infinite loops (e.g. let x = f(x)) *)
+--- a/libpolyml/elfexport.cpp
++++ b/libpolyml/elfexport.cpp
+@@ -115,6 +115,7 @@
+ #include "run_time.h"
+ #include "version.h"
+ #include "polystring.h"
++#include "timing.h"
+ 
+ #define sym_last_local_sym sym_data_section
+ 
+@@ -687,7 +688,7 @@
+     // Set the value to be the offset relative to the base of the area.  We have set a relocation
+     // already which will add the base of the area.
+     exports.rootFunction = useRela ? 0 : (void*)rootOffset;
+-    exports.timeStamp = time(NULL);
++    exports.timeStamp = getBuildTime();
+     exports.ioSpacing = ioSpacing;
+     exports.architecture = machineDependent->MachineArchitecture();
+     exports.rtsVersion = POLY_version_number;
+--- a/libpolyml/machoexport.cpp
++++ b/libpolyml/machoexport.cpp
+@@ -78,7 +78,7 @@
+ #include "run_time.h"
+ #include "version.h"
+ #include "polystring.h"
+-
++#include "timing.h"
+ 
+ // Mach-O seems to require each section to have a discrete virtual address range
+ // so we have to adjust various offsets to fit.
+@@ -492,7 +492,7 @@
+     // Set the value to be the offset relative to the base of the area.  We have set a relocation
+     // already which will add the base of the area.
+     exports.rootFunction = (void*)rootOffset;
+-    exports.timeStamp = time(NULL);
++    exports.timeStamp = getBuildTime();
+     exports.ioSpacing = ioSpacing;
+     exports.architecture = machineDependent->MachineArchitecture();
+     exports.rtsVersion = POLY_version_number;
+--- a/libpolyml/pecoffexport.cpp
++++ b/libpolyml/pecoffexport.cpp
+@@ -56,7 +56,7 @@
+ #include "../polyexports.h"
+ #include "version.h"
+ #include "polystring.h"
+-
++#include "timing.h"
+ 
+ #ifdef _DEBUG
+ /* MS C defines _DEBUG for debug builds. */
+@@ -184,8 +184,7 @@
+     unsigned i;
+     // These are written out as the description of the data.
+     exportDescription exports;
+-    time_t now;
+-    time(&now);
++    time_t now = getBuildTime();
+ 
+     sections = new IMAGE_SECTION_HEADER [memTableEntries+1]; // Plus one for the tables.
+ 
+@@ -198,7 +197,7 @@
+     fhdr.Machine = IMAGE_FILE_MACHINE_I386; // i386
+ #endif
+     fhdr.NumberOfSections = memTableEntries+1; // One for each area plus one for the tables.
+-    (void)time((time_t*)&fhdr.TimeDateStamp);
++    fhdr.TimeDateStamp = (DWORD)now;
+     //fhdr.NumberOfSymbols = memTableEntries+1; // One for each area plus "poly_exports"
+     fwrite(&fhdr, sizeof(fhdr), 1, exportFile); // Write it for the moment.
+ 
+--- a/libpolyml/pexport.cpp
++++ b/libpolyml/pexport.cpp
+@@ -30,10 +30,6 @@
+ #include <stdio.h>
+ #endif
+ 
+-#ifdef HAVE_TIME_H
+-#include <time.h>
+-#endif
+-
+ #ifdef HAVE_ERRNO_H
+ #include <errno.h>
+ #endif
+@@ -272,8 +268,6 @@
+ void PExport::exportStore(void)
+ {
+     unsigned i;
+-    time_t now;
+-    time(&now);
+ 
+     // Calculate a first guess for the map size based on the space size
+     totalBytes = 0;
+--- a/libpolyml/savestate.cpp
++++ b/libpolyml/savestate.cpp
+@@ -100,6 +100,7 @@
+ #include "machine_dep.h"
+ #include "osmem.h"
+ #include "gc.h" // For FullGC.
++#include "timing.h"
+ 
+ #ifdef _MSC_VER
+ // Don't tell me about ISO C++ changes.
+@@ -559,7 +560,7 @@
+         saveHeader.parentTimeStamp = hierarchyTable[newHierarchy-2]->timeStamp;
+         saveHeader.parentNameEntry = sizeof(TCHAR); // Always the first entry.
+     }
+-    saveHeader.timeStamp = time(NULL);
++    saveHeader.timeStamp = getBuildTime();
+     saveHeader.segmentDescrCount = exports.memTableEntries; // One segment for each space.
+     // Write out the header.
+     fwrite(&saveHeader, sizeof(saveHeader), 1, exports.exportFile);
+@@ -1348,7 +1349,7 @@
+         modHeader.rootSegment = mt->mtIndex;
+         modHeader.rootOffset = (char*)this->rootFunction - (char*)mt->mtAddr;
+     }
+-    modHeader.timeStamp = time(NULL);
++    modHeader.timeStamp = getBuildTime();
+     modHeader.segmentDescrCount = this->memTableEntries; // One segment for each space.
+     // Write out the header.
+     fwrite(&modHeader, sizeof(modHeader), 1, this->exportFile);
+--- a/libpolyml/timing.cpp
++++ b/libpolyml/timing.cpp
+@@ -99,6 +99,8 @@
+ #include <windows.h>
+ #endif
+ 
++#include <limits>
++
+ #include "locking.h"
+ #include "globals.h"
+ #include "arb.h"
+@@ -143,8 +145,10 @@
+ 
+ #if (defined(_WIN32) && ! defined(__CYGWIN__))
+ static FILETIME startTime;
++#define StrToLL _strtoi64
+ #else
+ static struct timeval startTime;
++#define StrToLL strtoll
+ #endif
+ 
+ #if(!(defined(HAVE_GMTIME_R) && defined(HAVE_LOCALTIME_R)))
+@@ -153,6 +157,9 @@
+ static PLock timeLock("Timing");
+ #endif
+ 
++#define XSTR(X) STR(X)
++#define STR(X)  #X
++
+ Handle timing_dispatch_c(TaskData *taskData, Handle args, Handle code)
+ {
+     unsigned c = get_C_unsigned(taskData, DEREFWORDHANDLE(code));
+@@ -513,3 +520,44 @@
+     gettimeofday(&startTime, NULL);
+ #endif
+ }
++
++// Windows headers define min/max macros, which messes up trying to use std::numeric_limits<T>::min/max()
++#ifdef min
++#undef min
++#endif
++#ifdef max
++#undef max
++#endif
++
++time_t getBuildTime(void)
++{
++    char *source_date_epoch = getenv("SOURCE_DATE_EPOCH");
++    if (source_date_epoch) {
++        errno = 0;
++        char *endptr;
++        long long epoch = StrToLL(source_date_epoch, &endptr, 10);
++        if ((errno == ERANGE && (epoch == LLONG_MIN || epoch == LLONG_MAX)) || (errno != 0 && epoch == 0)) {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: " XSTR(StrToLL) ": %s\n", strerror(errno));
++            goto err;
++        }
++        if (endptr == source_date_epoch) {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: No digits were found: %s\n", endptr);
++            goto err;
++        }
++        if (*endptr != '\0') {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: Trailing garbage: %s\n", endptr);
++            goto err;
++        }
++        if (epoch < (long long)std::numeric_limits<time_t>::min()) {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be greater than or equal to: %lld but was found to be: %lld\n", (long long)std::numeric_limits<time_t>::min(), epoch);
++            goto err;
++        }
++        if (epoch > (long long)std::numeric_limits<time_t>::max()) {
++            fprintf(stderr, "Environment variable $SOURCE_DATE_EPOCH: value must be smaller than or equal to: %lld but was found to be: %lld\n", (long long)std::numeric_limits<time_t>::max(), epoch);
++            goto err;
++        }
++        return (time_t) epoch;
++    }
++err:
++    return time(NULL);
++}
+--- a/libpolyml/timing.h
++++ b/libpolyml/timing.h
+@@ -105,4 +105,6 @@
+ extern float timevalToSeconds(const struct timeval *x);
+ #endif
+ 
++extern time_t getBuildTime(void);
++
+ #endif

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/polyml.git



More information about the debian-science-commits mailing list