mirror of
https://github.com/veracrypt/VeraCrypt.git
synced 2026-06-10 06:46:59 -05:00
Build: replace fixed SOURCE_DATE_EPOCH fallback
Keep caller-provided SOURCE_DATE_EPOCH authoritative and derive the automatic default through a shared helper used by the Makefile, direct CMake/CPack packaging, and the deb packaging wrapper. When repository metadata is available, use the HEAD commit timestamp without relying on git -C. Resolve the source root before probing Git so symlinked source paths still use the checkout HEAD. For source tarballs without .git, derive the fallback timestamp from the release date encoded in Common/Tcdefs.h instead of the stale 2020-01-01 constant. Add TC_RELEASE_DATE_DAY and validate it together with TC_RELEASE_DATE_YEAR, TC_RELEASE_DATE_MONTH, and TC_STR_RELEASE_DATE. Abort when no valid timestamp can be derived. For direct CMake invocation, initialize SOURCEPATH when the wrapper has not provided it, use the shared helper for derivation, validate the result, and export it for package targets. Also persist the configured epoch through CPACK_PROJECT_CONFIG_FILE so later standalone cpack --config runs export the same value before invoking package generators. Document that automatic git-checkout builds and release-tarball builds intentionally use different epochs; release reproducers should build from the tarball or set SOURCE_DATE_EPOCH explicitly.
This commit is contained in:
@@ -119,6 +119,14 @@ it is also available [online](https://veracrypt.jp/en/CompilingGuidelineLinux.ht
|
||||
4. If successful, the VeraCrypt executable should be located in the directory
|
||||
'Main'.
|
||||
|
||||
Reproducible build note: when `SOURCE_DATE_EPOCH` is not set, a build from a
|
||||
git checkout uses the HEAD commit timestamp, while a build from a release
|
||||
tarball uses the release date in `src/Common/Tcdefs.h` at 00:00 UTC. To
|
||||
reproduce official release artifacts from a git checkout, set
|
||||
`SOURCE_DATE_EPOCH` explicitly or build from the release tarball. Vendored
|
||||
VeraCrypt sources tracked in another git checkout are treated the same way and
|
||||
use that checkout's HEAD timestamp.
|
||||
|
||||
By default, a universal executable supporting both graphical and text user
|
||||
interface (through the switch --text) is built.
|
||||
On Linux, a console-only executable, which requires no GUI library, can be
|
||||
|
||||
+44
-12
@@ -27,23 +27,48 @@ else()
|
||||
endif()
|
||||
project(${PROJECT_NAME})
|
||||
|
||||
# SOURCE_DATE_EPOCH for the cpack-driven DEB pipeline.
|
||||
# Precedence: -DSOURCE_DATE_EPOCH=N, env, git HEAD, fixed fallback.
|
||||
# Re-exported to ENV so dpkg-deb/tar inherit it.
|
||||
# Source directory which contains the Makefile. Build scripts set this, but keep
|
||||
# direct cmake invocations working as well.
|
||||
if(NOT DEFINED ENV{SOURCEPATH})
|
||||
get_filename_component(_vc_sourcepath "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
set(ENV{SOURCEPATH} "${_vc_sourcepath}")
|
||||
endif()
|
||||
if("$ENV{SOURCEPATH}" STREQUAL "")
|
||||
get_filename_component(_vc_sourcepath "${CMAKE_CURRENT_SOURCE_DIR}/.." ABSOLUTE)
|
||||
set(ENV{SOURCEPATH} "${_vc_sourcepath}")
|
||||
endif()
|
||||
|
||||
# SOURCE_DATE_EPOCH for the cpack-driven packaging pipeline.
|
||||
# Precedence: -DSOURCE_DATE_EPOCH=N, env, git HEAD, Common/Tcdefs.h release date.
|
||||
# Re-exported to this process for package targets and written into
|
||||
# CPACK_PROJECT_CONFIG_FILE so later standalone "cpack --config" runs export
|
||||
# the same value before invoking package generators.
|
||||
if(NOT DEFINED SOURCE_DATE_EPOCH)
|
||||
if(DEFINED ENV{SOURCE_DATE_EPOCH})
|
||||
set(SOURCE_DATE_EPOCH "$ENV{SOURCE_DATE_EPOCH}")
|
||||
endif()
|
||||
endif()
|
||||
set(_derive_source_date_epoch FALSE)
|
||||
if(NOT DEFINED SOURCE_DATE_EPOCH)
|
||||
set(_derive_source_date_epoch TRUE)
|
||||
elseif("${SOURCE_DATE_EPOCH}" STREQUAL "")
|
||||
set(_derive_source_date_epoch TRUE)
|
||||
endif()
|
||||
if(_derive_source_date_epoch)
|
||||
execute_process(
|
||||
COMMAND sh "$ENV{SOURCEPATH}/Build/Tools/source_date_epoch.sh" "$ENV{SOURCEPATH}"
|
||||
OUTPUT_VARIABLE _source_date_epoch
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_VARIABLE _source_date_epoch_error
|
||||
RESULT_VARIABLE _source_date_epoch_rc)
|
||||
if(_source_date_epoch_rc EQUAL 0 AND NOT "${_source_date_epoch}" STREQUAL "")
|
||||
set(SOURCE_DATE_EPOCH "${_source_date_epoch}")
|
||||
else()
|
||||
execute_process(
|
||||
COMMAND git -C "$ENV{SOURCEPATH}" log -1 --pretty=%ct
|
||||
OUTPUT_VARIABLE _git_ct
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
ERROR_QUIET
|
||||
RESULT_VARIABLE _git_rc)
|
||||
if(_git_rc EQUAL 0 AND _git_ct)
|
||||
set(SOURCE_DATE_EPOCH "${_git_ct}")
|
||||
string(STRIP "${_source_date_epoch_error}" _source_date_epoch_error)
|
||||
if(_source_date_epoch_error)
|
||||
MESSAGE(FATAL_ERROR "SOURCE_DATE_EPOCH must be set, derivable from git, or derivable from Common/Tcdefs.h release date: ${_source_date_epoch_error}")
|
||||
else()
|
||||
set(SOURCE_DATE_EPOCH "1577836800")
|
||||
MESSAGE(FATAL_ERROR "SOURCE_DATE_EPOCH must be set, derivable from git, or derivable from Common/Tcdefs.h release date")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
@@ -52,6 +77,13 @@ if(NOT SOURCE_DATE_EPOCH MATCHES "^[0-9]+$")
|
||||
endif()
|
||||
message(STATUS "SOURCE_DATE_EPOCH = ${SOURCE_DATE_EPOCH}")
|
||||
set(ENV{SOURCE_DATE_EPOCH} "${SOURCE_DATE_EPOCH}")
|
||||
# Standalone "cpack --config CPackConfig.cmake" runs in a new process, so
|
||||
# persist the configure-time epoch into CPack's package-time config.
|
||||
configure_file(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/Tools/cpack_source_date_epoch.cmake.in"
|
||||
"${CMAKE_CURRENT_BINARY_DIR}/cpack_source_date_epoch.cmake"
|
||||
@ONLY)
|
||||
set(CPACK_PROJECT_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/cpack_source_date_epoch.cmake")
|
||||
# Avoid nondeterministic ordering from cpack 3.18+ parallel compression.
|
||||
set(CPACK_THREADS 1)
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Preserve configure-time SOURCE_DATE_EPOCH for standalone cpack --config runs.
|
||||
set(SOURCE_DATE_EPOCH "@SOURCE_DATE_EPOCH@")
|
||||
set(ENV{SOURCE_DATE_EPOCH} "${SOURCE_DATE_EPOCH}")
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Derive SOURCE_DATE_EPOCH for VeraCrypt build and packaging paths.
|
||||
# Precedence inside this helper is git HEAD, then the release date encoded in
|
||||
# Common/Tcdefs.h. Callers remain responsible for honoring an explicit
|
||||
# SOURCE_DATE_EPOCH before invoking this helper. The source root is resolved
|
||||
# before probing Git so symlinked build paths still use the checkout HEAD,
|
||||
# while release tarballs unpacked below unrelated repositories ignore the
|
||||
# parent repository and fall back to Common/Tcdefs.h.
|
||||
|
||||
if [ "$#" -ne 1 ]; then
|
||||
echo "Usage: $0 <source-root>" >&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
SOURCE_ROOT_INPUT=${1%/}
|
||||
if [ -z "$SOURCE_ROOT_INPUT" ]; then
|
||||
SOURCE_ROOT_INPUT=/
|
||||
fi
|
||||
SOURCE_ROOT=$(cd "$SOURCE_ROOT_INPUT" 2>/dev/null && pwd -P) || {
|
||||
echo "Error: $1 is not a readable directory" >&2
|
||||
exit 1
|
||||
}
|
||||
TCDEFS_H="$SOURCE_ROOT/Common/Tcdefs.h"
|
||||
|
||||
GIT_WORKTREE=
|
||||
GIT_SOURCE_PREFIX=
|
||||
SOURCE_ROOT_BASENAME=${SOURCE_ROOT##*/}
|
||||
|
||||
if [ -e "$SOURCE_ROOT/.git" ]; then
|
||||
GIT_WORKTREE="$SOURCE_ROOT"
|
||||
elif [ -e "$SOURCE_ROOT/../.git" ]; then
|
||||
GIT_WORKTREE=$(cd "$SOURCE_ROOT/.." 2>/dev/null && pwd -P)
|
||||
GIT_SOURCE_PREFIX="$SOURCE_ROOT_BASENAME/"
|
||||
fi
|
||||
|
||||
GIT_EPOCH=
|
||||
if [ -n "$GIT_WORKTREE" ] &&
|
||||
(cd "$GIT_WORKTREE" &&
|
||||
git rev-parse --is-inside-work-tree >/dev/null 2>&1 &&
|
||||
git ls-files --error-unmatch \
|
||||
"${GIT_SOURCE_PREFIX}Common/Tcdefs.h" \
|
||||
"${GIT_SOURCE_PREFIX}Build/Tools/source_date_epoch.sh" >/dev/null 2>&1); then
|
||||
GIT_EPOCH=$(cd "$GIT_WORKTREE" && git log -1 --pretty=%ct 2>/dev/null)
|
||||
fi
|
||||
case "$GIT_EPOCH" in
|
||||
''|*[!0-9]*)
|
||||
;;
|
||||
*)
|
||||
printf '%s\n' "$GIT_EPOCH"
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -r "$TCDEFS_H" ]; then
|
||||
echo "Error: $TCDEFS_H is not readable" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
RELEASE_EPOCH=$(awk '
|
||||
function leap(y) { return ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) }
|
||||
function month_number(name) {
|
||||
return (name == "January" ? 1 : name == "February" ? 2 : name == "March" ? 3 :
|
||||
name == "April" ? 4 : name == "May" ? 5 : name == "June" ? 6 :
|
||||
name == "July" ? 7 : name == "August" ? 8 : name == "September" ? 9 :
|
||||
name == "October" ? 10 : name == "November" ? 11 : name == "December" ? 12 : 0);
|
||||
}
|
||||
function mdays(m, y) { return (m == 2 ? 28 + leap(y) : (m == 4 || m == 6 || m == 9 || m == 11 ? 30 : 31)) }
|
||||
function epoch(y, m, d, days, i) {
|
||||
days = 0;
|
||||
for (i = 1970; i < y; i++) days += 365 + leap(i);
|
||||
for (i = 1; i < m; i++) days += mdays(i, y);
|
||||
days += d - 1;
|
||||
return days * 86400;
|
||||
}
|
||||
function is_number(value) { return (value ~ /^[0-9]+$/) }
|
||||
|
||||
/^[[:space:]]*#define[[:space:]]+TC_STR_RELEASE_DATE[[:space:]]+L"/ {
|
||||
date = $0;
|
||||
sub(/^.*L"/, "", date);
|
||||
sub(/".*$/, "", date);
|
||||
split(date, parts, /[ ,]+/);
|
||||
if (month_number(parts[1]) == 0 || !is_number(parts[2]) || !is_number(parts[3])) exit 1;
|
||||
date_month = month_number(parts[1]);
|
||||
date_day = parts[2] + 0;
|
||||
date_year = parts[3] + 0;
|
||||
seen_date = 1;
|
||||
}
|
||||
/^[[:space:]]*#define[[:space:]]+TC_RELEASE_DATE_YEAR[[:space:]]+/ {
|
||||
if (!is_number($3)) exit 1;
|
||||
year = $3 + 0;
|
||||
seen_year = 1;
|
||||
}
|
||||
/^[[:space:]]*#define[[:space:]]+TC_RELEASE_DATE_MONTH[[:space:]]+/ {
|
||||
if (!is_number($3)) exit 1;
|
||||
month = $3 + 0;
|
||||
seen_month = 1;
|
||||
}
|
||||
/^[[:space:]]*#define[[:space:]]+TC_RELEASE_DATE_DAY[[:space:]]+/ {
|
||||
if (!is_number($3)) exit 1;
|
||||
day = $3 + 0;
|
||||
seen_day = 1;
|
||||
}
|
||||
END {
|
||||
if (!seen_date || !seen_year || !seen_month || !seen_day) exit 1;
|
||||
if (year < 1970 || month < 1 || month > 12 || day < 1 || day > mdays(month, year)) exit 1;
|
||||
if (date_month != month || date_day != day || date_year != year) exit 1;
|
||||
printf "%d", epoch(year, month, day);
|
||||
}' "$TCDEFS_H") || {
|
||||
echo "Error: unable to derive SOURCE_DATE_EPOCH from $TCDEFS_H" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
case "$RELEASE_EPOCH" in
|
||||
''|*[!0-9]*)
|
||||
echo "Error: unable to derive SOURCE_DATE_EPOCH from $TCDEFS_H" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
printf '%s\n' "$RELEASE_EPOCH"
|
||||
@@ -15,20 +15,6 @@ set -e
|
||||
# not reproducible. Pin it for the whole packaging run.
|
||||
umask 022
|
||||
|
||||
# Compute and export SOURCE_DATE_EPOCH so cmake/cpack inherit it (they get
|
||||
# an empty env from this shell otherwise). Precedence: caller, git HEAD,
|
||||
# fallback constant matching src/Makefile and CMakeLists.txt.
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
SOURCE_DATE_EPOCH=$(git -C "$(dirname "$0")/../.." log -1 --pretty=%ct 2>/dev/null || echo 1577836800)
|
||||
fi
|
||||
case "$SOURCE_DATE_EPOCH" in
|
||||
''|*[!0-9]*)
|
||||
echo "Error: SOURCE_DATE_EPOCH must be a non-negative Unix timestamp" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
export SOURCE_DATE_EPOCH
|
||||
|
||||
# Absolute path to this script
|
||||
export SCRIPT=$(readlink -f "$0")
|
||||
# Absolute path this script is in
|
||||
@@ -38,6 +24,23 @@ export SOURCEPATH=$(readlink -f "$SCRIPTPATH/..")
|
||||
# Directory where the VeraCrypt has been checked out
|
||||
export PARENTDIR=$(readlink -f "$SCRIPTPATH/../../..")
|
||||
|
||||
# Compute and export SOURCE_DATE_EPOCH so cmake/cpack inherit it (they get
|
||||
# an empty env from this shell otherwise). Precedence: caller, git HEAD,
|
||||
# Common/Tcdefs.h release date.
|
||||
if [ -z "${SOURCE_DATE_EPOCH:-}" ]; then
|
||||
SOURCE_DATE_EPOCH=$(sh "$SOURCEPATH/Build/Tools/source_date_epoch.sh" "$SOURCEPATH") || {
|
||||
echo "Error: SOURCE_DATE_EPOCH must be set, derivable from git, or derivable from Common/Tcdefs.h release date" >&2
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
case "$SOURCE_DATE_EPOCH" in
|
||||
''|*[!0-9]*)
|
||||
echo "Error: SOURCE_DATE_EPOCH must be a non-negative Unix timestamp" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
export SOURCE_DATE_EPOCH
|
||||
|
||||
# Check the condition of wxBuildConsole and wxWidgets-3.2.5 in the original PARENTDIR
|
||||
if [ -d "$PARENTDIR/wxBuildConsole" ]; then
|
||||
echo "Using existing PARENTDIR: $PARENTDIR, wxBuildConsole is present."
|
||||
|
||||
@@ -76,6 +76,7 @@ extern unsigned short _rotl16(unsigned short value, unsigned char shift);
|
||||
#define TC_STR_RELEASE_DATE L"June 4, 2026"
|
||||
#define TC_RELEASE_DATE_YEAR 2026
|
||||
#define TC_RELEASE_DATE_MONTH 6
|
||||
#define TC_RELEASE_DATE_DAY 4
|
||||
|
||||
#define BYTES_PER_KB 1024LL
|
||||
#define BYTES_PER_MB 1048576LL
|
||||
|
||||
+4
-4
@@ -601,10 +601,10 @@ LFLAGS := $(LFLAGS) $(TC_EXTRA_LFLAGS)
|
||||
# is honoured by GCC/Clang for any residual __DATE__/__TIME__ expansion, by
|
||||
# ar/ranlib in deterministic mode, and by tar, gzip and makeself for archive
|
||||
# member timestamps. If the caller does not set it, derive a stable value
|
||||
# from the HEAD commit; fall back to a fixed constant for tarball builds with
|
||||
# no git tree so that unattended builds are still deterministic.
|
||||
# from the HEAD commit; fall back to the release date embedded in
|
||||
# Common/Tcdefs.h for source-tarball builds without a git checkout.
|
||||
ifndef SOURCE_DATE_EPOCH
|
||||
export SOURCE_DATE_EPOCH := $(shell git -C $(BASE_DIR) log -1 --pretty=%ct 2>/dev/null || echo 1577836800)
|
||||
export SOURCE_DATE_EPOCH := $(shell sh "$(BASE_DIR)/Build/Tools/source_date_epoch.sh" "$(BASE_DIR)")
|
||||
export VC_SOURCE_DATE_EPOCH_AUTO := 1
|
||||
endif
|
||||
override export SOURCE_DATE_EPOCH := $(value SOURCE_DATE_EPOCH)
|
||||
@@ -620,7 +620,7 @@ SOURCE_DATE_EPOCH_REMAINDER := $(subst 7,,$(SOURCE_DATE_EPOCH_REMAINDER))
|
||||
SOURCE_DATE_EPOCH_REMAINDER := $(subst 8,,$(SOURCE_DATE_EPOCH_REMAINDER))
|
||||
SOURCE_DATE_EPOCH_REMAINDER := $(subst 9,,$(SOURCE_DATE_EPOCH_REMAINDER))
|
||||
ifeq "$(SOURCE_DATE_EPOCH)" ""
|
||||
$(error SOURCE_DATE_EPOCH must be a non-negative Unix timestamp)
|
||||
$(error SOURCE_DATE_EPOCH must be set, derivable from git, or derivable from Common/Tcdefs.h release date)
|
||||
endif
|
||||
ifneq "$(SOURCE_DATE_EPOCH_REMAINDER)" ""
|
||||
$(error SOURCE_DATE_EPOCH must contain decimal digits only)
|
||||
|
||||
Reference in New Issue
Block a user