From 875e7d173aec7eda57240b42fe9502bdacbf3aa9 Mon Sep 17 00:00:00 2001 From: "Keith W. Campbell" Date: Mon, 26 Sep 2022 12:37:10 -0400 Subject: [PATCH] Avoid non-portable uses of date utility On some platforms, the date utility doesn't support the "%s" format specifier or supports neither the "-f" option nor the "-j" option. Use the boot jdk to run a java program instead. Signed-off-by: Keith W. Campbell --- make/InitSupport.gmk | 6 ++- make/autoconf/jdk-options.m4 | 20 +++----- make/autoconf/util.m4 | 23 ++------- make/common/Utils.gmk | 14 ++--- make/src/classes/DateUtil.java | 94 ++++++++++++++++++++++++++++++++++ 5 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 make/src/classes/DateUtil.java diff --git a/make/InitSupport.gmk b/make/InitSupport.gmk index 76fc778eb26..4cac3bf1d3c 100644 --- a/make/InitSupport.gmk +++ b/make/InitSupport.gmk @@ -23,6 +23,10 @@ # questions. # +# =========================================================================== +# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved +# =========================================================================== + ################################################################################ # This file contains helper functions for Init.gmk. # It is divided in two parts, depending on if a SPEC is present or not @@ -311,7 +315,7 @@ else # $(HAS_SPEC)=true define SetupReproducibleBuild ifeq ($$(SOURCE_DATE), updated) # For static values of SOURCE_DATE (not "updated"), these are set in spec.gmk - export SOURCE_DATE_EPOCH := $$(shell $$(DATE) +"%s") + export SOURCE_DATE_EPOCH := $$(shell $$(JAVA) $$(TOPDIR)/make/src/classes/DateUtil.java) export SOURCE_DATE_ISO_8601 := $$(call EpochToISO8601, $$(SOURCE_DATE_EPOCH)) endif endef diff --git a/make/autoconf/jdk-options.m4 b/make/autoconf/jdk-options.m4 index 05bff5d5001..fd4090aa9f1 100644 --- a/make/autoconf/jdk-options.m4 +++ b/make/autoconf/jdk-options.m4 @@ -23,6 +23,10 @@ # questions. # +# =========================================================================== +# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved +# =========================================================================== + ############################################################################### # Set the debug level # release: no debug information, all optimizations, no asserts. @@ -203,13 +207,9 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_JDK_OPTIONS], elif test "x$with_copyright_year" != x; then COPYRIGHT_YEAR="$with_copyright_year" elif test "x$SOURCE_DATE" != xupdated; then - if test "x$IS_GNU_DATE" = xyes; then - COPYRIGHT_YEAR=`$DATE --date=@$SOURCE_DATE +%Y` - else - COPYRIGHT_YEAR=`$DATE -j -f %s $SOURCE_DATE +%Y` - fi + COPYRIGHT_YEAR=`$JAVA $TOPDIR/make/src/classes/DateUtil.java --format=yyyy --date="$SOURCE_DATE_EPOCH"` else - COPYRIGHT_YEAR=`$DATE +'%Y'` + COPYRIGHT_YEAR=`$JAVA $TOPDIR/make/src/classes/DateUtil.java --format=yyyy` fi AC_SUBST(COPYRIGHT_YEAR) @@ -676,7 +676,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], AC_MSG_RESULT([determined at build time, from 'updated']) elif test "x$with_source_date" = xcurrent; then # Set the current time - SOURCE_DATE=$($DATE +"%s") + SOURCE_DATE=$($JAVA $TOPDIR/make/src/classes/DateUtil.java) AC_MSG_RESULT([$SOURCE_DATE, from 'current']) elif test "x$with_source_date" = xversion; then # Use the date from version-numbers.conf @@ -708,11 +708,7 @@ AC_DEFUN_ONCE([JDKOPT_SETUP_REPRODUCIBLE_BUILD], # If we have a fixed value for SOURCE_DATE, we need to set SOURCE_DATE_EPOCH # for the rest of configure. SOURCE_DATE_EPOCH="$SOURCE_DATE" - if test "x$IS_GNU_DATE" = xyes; then - SOURCE_DATE_ISO_8601=`$DATE --utc --date="@$SOURCE_DATE" +"$ISO_8601_FORMAT_STRING" 2> /dev/null` - else - SOURCE_DATE_ISO_8601=`$DATE -u -j -f "%s" "$SOURCE_DATE" +"$ISO_8601_FORMAT_STRING" 2> /dev/null` - fi + SOURCE_DATE_ISO_8601=`$JAVA $TOPDIR/make/src/classes/DateUtil.java --date="$SOURCE_DATE" --format="yyyy-MM-dd'T'HH:mm:ss'Z'"` fi AC_SUBST(SOURCE_DATE) diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4 index d2171338d00..2db26b253dc 100644 --- a/make/autoconf/util.m4 +++ b/make/autoconf/util.m4 @@ -23,6 +23,10 @@ # questions. # +# =========================================================================== +# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved +# =========================================================================== + m4_include([util_paths.m4]) ############################################################################### @@ -234,24 +238,7 @@ AC_DEFUN([UTIL_GET_MATCHING_VALUES], # $2: input date/time string AC_DEFUN([UTIL_GET_EPOCH_TIMESTAMP], [ - if test "x$IS_GNU_DATE" = xyes; then - # GNU date - timestamp=$($DATE --utc --date=$2 +"%s" 2> /dev/null) - else - # BSD date - # ISO-8601 date&time in Zulu 'date'T'time'Z - timestamp=$($DATE -u -j -f "%FT%TZ" "$2" "+%s" 2> /dev/null) - if test "x$timestamp" = x; then - # BSD date cannot handle trailing milliseconds. - # Try again ignoring characters at end - timestamp=$($DATE -u -j -f "%Y-%m-%dT%H:%M:%S" "$2" "+%s" 2> /dev/null) - fi - if test "x$timestamp" = x; then - # Perhaps the time was missing. - timestamp=$($DATE -u -j -f "%FT%TZ" "$2""T00:00:00Z" "+%s" 2> /dev/null) - fi - fi - $1=$timestamp + $1=$($JAVA $TOPDIR/make/src/classes/DateUtil.java --date="$2") ]) ############################################################################### diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk index 00e73f7dd6c..11b10e48aa9 100644 --- a/make/common/Utils.gmk +++ b/make/common/Utils.gmk @@ -23,6 +23,10 @@ # questions. # +# =========================================================================== +# (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved +# =========================================================================== + ifeq (,$(_MAKEBASE_GMK)) $(error You must include MakeBase.gmk prior to including Utils.gmk) endif @@ -227,15 +231,7 @@ Or = \ # Convert an UNIX epoch based timestamp (as an integer) to an ISO 8601 date # string. # Param 1 - timestamp -ifeq ($(IS_GNU_DATE), yes) - EpochToISO8601 = \ - $(shell $(DATE) --utc --date="@$(strip $1)" \ - +"$(ISO_8601_FORMAT_STRING)" 2> /dev/null) -else - EpochToISO8601 = \ - $(shell $(DATE) -u -j -f "%s" "$(strip $1)" \ - +"$(ISO_8601_FORMAT_STRING)" 2> /dev/null) -endif +EpochToISO8601 = $(shell $(JAVA) $(TOPDIR)/make/src/classes/DateUtil.java --date="$(strip $1)" --format="yyyy-MM-dd'T'HH:mm:ss'Z'") ################################################################################ # Parse a multiple-keyword variable, like FOO="KEYWORD1=val1;KEYWORD2=val2;..." diff --git a/make/src/classes/DateUtil.java b/make/src/classes/DateUtil.java new file mode 100644 index 00000000000..914689ad810 --- /dev/null +++ b/make/src/classes/DateUtil.java @@ -0,0 +1,94 @@ +/* + * =========================================================================== + * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved + * =========================================================================== + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * IBM designates this particular file as subject to the "Classpath" exception + * as provided by IBM in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, see . + * =========================================================================== + */ +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Locale; + +public class DateUtil { + + public static void main(String... args) { + String date = ""; + String format = ""; + + for (String arg : args) { + if (arg.startsWith("--date=")) { + date = arg.substring(7).trim(); + } else if (arg.startsWith("--format=")) { + format = arg.substring(9).trim(); + } else { + showUsageAndExit(); + } + } + + LocalDateTime time = parseTime(date); + + if (format.isEmpty()) { + System.out.println(time.toEpochSecond(ZoneOffset.UTC)); + } else { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern(format, Locale.ROOT); + + System.out.println(formatter.format(time)); + } + } + + private static LocalDateTime parseTime(String text) { + if (text.isEmpty()) { + return LocalDateTime.now(ZoneOffset.UTC); + } + + if (text.matches("\\d+")) { + return LocalDateTime.ofEpochSecond(Long.parseLong(text), 0, ZoneOffset.UTC); + } + + try { + return LocalDateTime.ofInstant(Instant.parse(text), ZoneOffset.UTC); + } catch (DateTimeParseException e) { + // try next format + } + + try { + return LocalDateTime.parse(text); + } catch (DateTimeParseException e) { + // try next format + } + + try { + return LocalDate.parse(text).atStartOfDay(); + } catch (DateTimeParseException e) { + System.err.format("Cannot parse time: '%s'%n", text); + System.exit(1); + return null; + } + } + + private static void showUsageAndExit() { + System.err.println("Usage: DateUtil [options]"); + System.err.println(" --date=