[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", §ionStrings);
+ unsigned long dataName = makeStringTableEntry(".data", §ionStrings);
+ unsigned long dataRelName = makeStringTableEntry(useRela ? ".rela.data" : ".rel.data", §ionStrings);
+ unsigned long textName = makeStringTableEntry(".text", §ionStrings);
+@@ -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