1
0
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:
Mounir IDRASSI
2026-06-05 17:44:10 +09:00
parent fd80bc0679
commit f77d0c0760
7 changed files with 198 additions and 30 deletions
+8
View File
@@ -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 4. If successful, the VeraCrypt executable should be located in the directory
'Main'. '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 By default, a universal executable supporting both graphical and text user
interface (through the switch --text) is built. interface (through the switch --text) is built.
On Linux, a console-only executable, which requires no GUI library, can be On Linux, a console-only executable, which requires no GUI library, can be
+44 -12
View File
@@ -27,23 +27,48 @@ else()
endif() endif()
project(${PROJECT_NAME}) project(${PROJECT_NAME})
# SOURCE_DATE_EPOCH for the cpack-driven DEB pipeline. # Source directory which contains the Makefile. Build scripts set this, but keep
# Precedence: -DSOURCE_DATE_EPOCH=N, env, git HEAD, fixed fallback. # direct cmake invocations working as well.
# Re-exported to ENV so dpkg-deb/tar inherit it. 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(NOT DEFINED SOURCE_DATE_EPOCH)
if(DEFINED ENV{SOURCE_DATE_EPOCH}) if(DEFINED ENV{SOURCE_DATE_EPOCH})
set(SOURCE_DATE_EPOCH "$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() else()
execute_process( string(STRIP "${_source_date_epoch_error}" _source_date_epoch_error)
COMMAND git -C "$ENV{SOURCEPATH}" log -1 --pretty=%ct if(_source_date_epoch_error)
OUTPUT_VARIABLE _git_ct MESSAGE(FATAL_ERROR "SOURCE_DATE_EPOCH must be set, derivable from git, or derivable from Common/Tcdefs.h release date: ${_source_date_epoch_error}")
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET
RESULT_VARIABLE _git_rc)
if(_git_rc EQUAL 0 AND _git_ct)
set(SOURCE_DATE_EPOCH "${_git_ct}")
else() 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() endif()
endif() endif()
@@ -52,6 +77,13 @@ if(NOT SOURCE_DATE_EPOCH MATCHES "^[0-9]+$")
endif() endif()
message(STATUS "SOURCE_DATE_EPOCH = ${SOURCE_DATE_EPOCH}") message(STATUS "SOURCE_DATE_EPOCH = ${SOURCE_DATE_EPOCH}")
set(ENV{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. # Avoid nondeterministic ordering from cpack 3.18+ parallel compression.
set(CPACK_THREADS 1) 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}")
+121
View File
@@ -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"
+17 -14
View File
@@ -15,20 +15,6 @@ set -e
# not reproducible. Pin it for the whole packaging run. # not reproducible. Pin it for the whole packaging run.
umask 022 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 # Absolute path to this script
export SCRIPT=$(readlink -f "$0") export SCRIPT=$(readlink -f "$0")
# Absolute path this script is in # Absolute path this script is in
@@ -38,6 +24,23 @@ export SOURCEPATH=$(readlink -f "$SCRIPTPATH/..")
# Directory where the VeraCrypt has been checked out # Directory where the VeraCrypt has been checked out
export PARENTDIR=$(readlink -f "$SCRIPTPATH/../../..") 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 # Check the condition of wxBuildConsole and wxWidgets-3.2.5 in the original PARENTDIR
if [ -d "$PARENTDIR/wxBuildConsole" ]; then if [ -d "$PARENTDIR/wxBuildConsole" ]; then
echo "Using existing PARENTDIR: $PARENTDIR, wxBuildConsole is present." echo "Using existing PARENTDIR: $PARENTDIR, wxBuildConsole is present."
+1
View File
@@ -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_STR_RELEASE_DATE L"June 4, 2026"
#define TC_RELEASE_DATE_YEAR 2026 #define TC_RELEASE_DATE_YEAR 2026
#define TC_RELEASE_DATE_MONTH 6 #define TC_RELEASE_DATE_MONTH 6
#define TC_RELEASE_DATE_DAY 4
#define BYTES_PER_KB 1024LL #define BYTES_PER_KB 1024LL
#define BYTES_PER_MB 1048576LL #define BYTES_PER_MB 1048576LL
+4 -4
View File
@@ -601,10 +601,10 @@ LFLAGS := $(LFLAGS) $(TC_EXTRA_LFLAGS)
# is honoured by GCC/Clang for any residual __DATE__/__TIME__ expansion, by # 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 # 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 # 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 # from the HEAD commit; fall back to the release date embedded in
# no git tree so that unattended builds are still deterministic. # Common/Tcdefs.h for source-tarball builds without a git checkout.
ifndef SOURCE_DATE_EPOCH 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 export VC_SOURCE_DATE_EPOCH_AUTO := 1
endif endif
override export SOURCE_DATE_EPOCH := $(value SOURCE_DATE_EPOCH) 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 8,,$(SOURCE_DATE_EPOCH_REMAINDER))
SOURCE_DATE_EPOCH_REMAINDER := $(subst 9,,$(SOURCE_DATE_EPOCH_REMAINDER)) SOURCE_DATE_EPOCH_REMAINDER := $(subst 9,,$(SOURCE_DATE_EPOCH_REMAINDER))
ifeq "$(SOURCE_DATE_EPOCH)" "" 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 endif
ifneq "$(SOURCE_DATE_EPOCH_REMAINDER)" "" ifneq "$(SOURCE_DATE_EPOCH_REMAINDER)" ""
$(error SOURCE_DATE_EPOCH must contain decimal digits only) $(error SOURCE_DATE_EPOCH must contain decimal digits only)