This is a CMake configure check that fails if year 2038 can't be handled.
cmake -B build
Certain platforms default or have defaulted to use a 32-bit time_t
, which will
overflow in year 2038.
To check if the platform uses a 64-bit time_t
, use code like this
Gist.
cmake_minimum_required(VERSION 3.20) | |
project(lang LANGUAGES C) | |
include(CheckSourceRuns) | |
include(CheckTypeSize) | |
check_type_size("time_t" TIME_T_SIZE) | |
if(NOT TIME_T_SIZE GREATER_EQUAL 8) | |
set(CMAKE_REQUIRED_DEFINITIONS -D_TIME_BITS=64) | |
message(STATUS "Trying ${CMAKE_REQUIRED_DEFINITIONS} to get 64-bit time_t") | |
check_type_size("time_t" TIME_T_SIZE_64) | |
if(TIME_T_SIZE_64 EQUAL 0) | |
message("multiple architectures detected.") | |
elseif(TIME_T_SIZE_64 LESS 8) | |
message(FATAL_ERROR "time_t is not 64-bit") | |
endif() | |
message("Need definition ${CMAKE_REQUIRED_DEFINITIONS} to use 64-bit time_t") | |
endif() | |
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/time2038.c src) | |
check_source_runs(C "${src}" OK2038) | |
if(NOT OK2038) | |
message(FATAL_ERROR "time_t is not 64-bit") | |
endif() |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <time.h> | |
int main(void) { | |
// January 19, 2038, 03:14:08 UTC (just before the 2038 problem boundary) | |
time_t y2038 = 0x7FFFFFFF; | |
// One second after (after the problematic timestamp) | |
time_t post_y2038 = y2038 + 1; | |
struct tm* pre_time = gmtime(&y2038); | |
struct tm* post_time = gmtime(&post_y2038); | |
printf("Testing time_t size and Year 2038 compatibility:\n"); | |
printf("Size of time_t: %zu bytes\n", sizeof(time_t)); | |
printf("Time just before Y2038 problem: %d-%02d-%02d %02d:%02d:%02d\n", | |
pre_time->tm_year + 1900, pre_time->tm_mon + 1, pre_time->tm_mday, | |
pre_time->tm_hour, pre_time->tm_min, pre_time->tm_sec); | |
printf("Time just after Y2038 problem: %d-%02d-%02d %02d:%02d:%02d\n", | |
post_time->tm_year + 1900, post_time->tm_mon + 1, post_time->tm_mday, | |
post_time->tm_hour, post_time->tm_min, post_time->tm_sec); | |
// Check if the time correctly wraps to 2038 | |
if (post_time->tm_year + 1900 >= 2038){ | |
printf("PASS: time_t can handle dates after January 19, 2038\n"); | |
return EXIT_SUCCESS; | |
} | |
fprintf(stderr, "FAIL: time_t cannot handle dates after January 19, 2038\n"); | |
return EXIT_FAILURE; | |
} |