newlib: auto-detect sizeof(time_t)

To make the transition from 32-bit time_t to 64-bit time_t smoother,
detect the size of this type in CMake and remove the manual option in
Kconfig.
The information about 64-bit time_t support is moved from Kconfig help
string into the "system time" section of the API reference.
This commit is contained in:
Ivan Grokhotkov 2022-01-06 18:02:09 +01:00
parent bbe8aabca0
commit d2b894862c
9 changed files with 71 additions and 84 deletions

View File

@ -209,6 +209,16 @@ if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
list(APPEND compile_options "-fno-use-cxa-atexit") list(APPEND compile_options "-fno-use-cxa-atexit")
endif() endif()
# For the transition period from 32-bit time_t to 64-bit time_t,
# auto-detect the size of this type and set corresponding variable.
include(CheckTypeSize)
check_type_size("time_t" TIME_T_SIZE)
if(TIME_T_SIZE)
idf_build_set_property(TIME_T_SIZE ${TIME_T_SIZE})
else()
message(FATAL_ERROR "Failed to determine sizeof(time_t)")
endif()
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND) idf_build_set_property(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND) idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)

20
Kconfig
View File

@ -104,26 +104,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
default 0x000E if IDF_TARGET_ESP32H2_BETA_VERSION_2 # ESP32H2-TODO: IDF-3475 default 0x000E if IDF_TARGET_ESP32H2_BETA_VERSION_2 # ESP32H2-TODO: IDF-3475
default 0xFFFF default 0xFFFF
menu "SDK tool configuration"
config SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
bool "Toolchain supports time_t wide 64-bits"
default n
help
Enable this option in case you have a custom toolchain which supports time_t wide 64-bits.
This option checks time_t is 64-bits and disables ROM time functions
to use the time functions from the toolchain instead.
This option allows resolving the Y2K38 problem.
See "Setup Linux Toolchain from Scratch" to build
a custom toolchain which supports 64-bits time_t.
Note: ESP-IDF does not currently come with any pre-compiled toolchain
that supports 64-bit wide time_t.
This will change in a future major release,
but currently 64-bit time_t requires a custom built toolchain.
endmenu # SDK tool configuration
menu "Build type" menu "Build type"

View File

@ -57,6 +57,8 @@ else()
rom_linker_script("libgcc") rom_linker_script("libgcc")
endif() endif()
idf_build_get_property(time_t_size TIME_T_SIZE)
if(BOOTLOADER_BUILD) if(BOOTLOADER_BUILD)
if(target STREQUAL "esp32") if(target STREQUAL "esp32")
rom_linker_script("newlib-funcs") rom_linker_script("newlib-funcs")
@ -91,19 +93,20 @@ else() # Regular app build
rom_linker_script("syscalls") rom_linker_script("syscalls")
if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND) if(NOT CONFIG_SPIRAM_CACHE_WORKAROUND)
# ESP32 only: these ROM functions may only be used if PSRAM cache workaround is disabled.
# Otherwise we need to link to a multilib version of libc compiled with PSRAM workaround.
rom_linker_script("newlib-funcs") rom_linker_script("newlib-funcs")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined if(time_t_size EQUAL 4)
# then all time functions from the ROM memory will not be linked. # The ROM functions listed in this linker script depend on sizeof(time_t).
# Instead, those functions can be used from the toolchain by ESP-IDF. # Since ROM for ESP32 was compiled for 32-bit time_t, only link these functions
# if the toolchain is also using 32-bit time_t.
rom_linker_script("newlib-time") rom_linker_script("newlib-time")
# Include in newlib nano from ROM only if SPIRAM cache workaround is disabled
# and sizeof(time_t) == 4
if(CONFIG_NEWLIB_NANO_FORMAT) if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano") rom_linker_script("newlib-nano")
endif() endif()
endif() endif()
endif() endif()
@ -120,52 +123,48 @@ else() # Regular app build
rom_linker_script("newlib-data") rom_linker_script("newlib-data")
rom_linker_script("spiflash") rom_linker_script("spiflash")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS) if(time_t_size EQUAL 4)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined # The ROM functions listed in this linker script depend on sizeof(time_t).
# then all time functions from the ROM memory will not be linked. # Since ROM for ESP32-S2 was compiled for 32-bit time_t, only link these functions
# Instead, those functions can be used from the toolchain by ESP-IDF. # if the toolchain is also using 32-bit time_t.
rom_linker_script("newlib-time")
if(CONFIG_NEWLIB_NANO_FORMAT) if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano") rom_linker_script("newlib-nano")
endif() endif()
rom_linker_script("newlib-time")
endif() endif()
# descirptors used by ROM code
target_sources(${COMPONENT_LIB} PRIVATE "esp32s2/usb_descriptors.c")
elseif(target STREQUAL "esp32s3") elseif(target STREQUAL "esp32s3")
rom_linker_script("newlib") rom_linker_script("newlib")
rom_linker_script("version") rom_linker_script("version")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS) if(time_t_size EQUAL 4)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined # The ROM functions listed in this linker script depend on sizeof(time_t).
# then all time functions from the ROM memory will not be linked. # Since ROM for ESP32-S3 was compiled for 32-bit time_t, only link these functions
# Instead, those functions can be used from the toolchain by ESP-IDF. # if the toolchain is also using 32-bit time_t.
rom_linker_script("newlib-time")
if(CONFIG_NEWLIB_NANO_FORMAT) if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano") rom_linker_script("newlib-nano")
endif() endif()
rom_linker_script("newlib-time")
endif() endif()
elseif(target STREQUAL "esp32c3") elseif(target STREQUAL "esp32c3")
rom_linker_script("newlib") rom_linker_script("newlib")
rom_linker_script("version") rom_linker_script("version")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS) if(time_t_size EQUAL 4)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined # The ROM functions listed in this linker script depend on sizeof(time_t).
# then all time functions from the ROM memory will not be linked. # Since ROM for ESP32-C3 was compiled for 32-bit time_t, only link these functions
# Instead, those functions can be used from the toolchain by ESP-IDF. # if the toolchain is also using 32-bit time_t.
rom_linker_script("newlib-time")
if(CONFIG_NEWLIB_NANO_FORMAT) if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano") rom_linker_script("newlib-nano")
endif() endif()
rom_linker_script("newlib-time")
endif() endif()
if(CONFIG_ESP32C3_REV_MIN_3) if(CONFIG_ESP32C3_REV_MIN_3)
@ -176,23 +175,23 @@ else() # Regular app build
rom_linker_script("newlib") rom_linker_script("newlib")
rom_linker_script("version") rom_linker_script("version")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS) if(CONFIG_NEWLIB_NANO_FORMAT AND time_t_size EQUAL 4)
if(CONFIG_NEWLIB_NANO_FORMAT) # nano formatting functions in ROM are built for 32-bit time_t,
# only link them if the toolchain is also using 32-bit time_t and nano formatting was requested.
rom_linker_script("newlib-nano") rom_linker_script("newlib-nano")
endif() endif()
endif()
elseif(target STREQUAL "esp8684") elseif(target STREQUAL "esp8684")
rom_linker_script("newlib") rom_linker_script("newlib")
rom_linker_script("version") rom_linker_script("version")
rom_linker_script("mbedtls") rom_linker_script("mbedtls")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS) if(CONFIG_NEWLIB_NANO_FORMAT AND time_t_size EQUAL 4)
if(CONFIG_NEWLIB_NANO_FORMAT) # nano formatting functions in ROM are built for 32-bit time_t,
# only link them if the toolchain is also using 32-bit time_t and nano formatting was requested.
rom_linker_script("newlib-nano") rom_linker_script("newlib-nano")
endif() endif()
endif() endif()
endif()
if(CONFIG_IDF_TARGET_ARCH_XTENSA) if(CONFIG_IDF_TARGET_ARCH_XTENSA)
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=longjmp") target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=longjmp")

View File

@ -1,4 +1,5 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <math.h> #include <math.h>
#include "unity.h" #include "unity.h"
#include "driver/adc.h" #include "driver/adc.h"
@ -446,8 +447,7 @@ TEST_CASE("test posix_timers clock_... functions", "[newlib]")
test_posix_timers_clock(); test_posix_timers_clock();
} }
#ifdef CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS #ifndef _USE_LONG_TIME_T
#include <string.h>
static struct timeval get_time(const char *desc, char *buffer) static struct timeval get_time(const char *desc, char *buffer)
{ {
@ -533,7 +533,7 @@ TEST_CASE("test time functions wide 64 bits", "[newlib]")
} }
} }
#endif // CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS #endif // !_USE_LONG_TIME_T
#if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) && defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER ) #if defined( CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER ) && defined( CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER )

View File

@ -1,16 +1,8 @@
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD /*
// * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
// Licensed under the Apache License, Version 2.0 (the "License"); *
// you may not use this file except in compliance with the License. * SPDX-License-Identifier: Apache-2.0
// You may obtain a copy of the License at */
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <errno.h> #include <errno.h>
#include <stdlib.h> #include <stdlib.h>
@ -37,12 +29,6 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#ifdef CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
_Static_assert(sizeof(time_t) == 8, "The toolchain does not support time_t wide 64-bits");
#else
_Static_assert(sizeof(time_t) == 4, "The toolchain supports time_t wide 64-bits. Please enable CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS.");
#endif
#if !CONFIG_ESP_TIME_FUNCS_USE_NONE #if !CONFIG_ESP_TIME_FUNCS_USE_NONE
#define IMPL_NEWLIB_TIME_FUNCS 1 #define IMPL_NEWLIB_TIME_FUNCS 1
#endif #endif

View File

@ -133,8 +133,8 @@ menu "SPIFFS Configuration"
If the chip already has the spiffs image with the time field = 32 bits If the chip already has the spiffs image with the time field = 32 bits
then this option cannot be applied in this case. then this option cannot be applied in this case.
Erase it first before using this option. Erase it first before using this option.
To resolve the Y2K38 problem for the spiffs, use a toolchain with support To resolve the Y2K38 problem for the spiffs, use a toolchain with
time_t 64 bits (see SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS). 64-bit time_t support.
menu "Debug Configuration" menu "Debug Configuration"

View File

@ -130,6 +130,21 @@ To set local timezone, use the following POSIX functions:
Once these steps are completed, call the standard C library function ``localtime()``, and it will return correct local time taking into account the time zone offset and daylight saving time. Once these steps are completed, call the standard C library function ``localtime()``, and it will return correct local time taking into account the time zone offset and daylight saving time.
64-bit ``time_t``
-----------------
ESP-IDF uses 32-bit ``time_t`` type by default. To address Y2K38 issue, you may need to use 64-bit ``time_t`` type when building the application.
Currently this requires building the cross-compiler toolchain from scratch. See the instructions for building the toolchain in :doc:`/get-started/linux-setup-scratch`. To enable 64-bit ``time_t`` support in the toolchain, you need to remove the ``--enable-newlib-long-time_t`` option from the ``crosstool-NG/samples/xtensa-esp32-elf/crosstool.config`` file before building the toolchain.
If you need to make the program compatible with both 32-bit and 64-bit ``time_t``, you may use the following methods:
- In C or C++ source files, ``_USE_LONG_TIME_T`` preprocessor macro will be defined if 32-bit ``time_t`` is used. You need to include ``<sys/types.h>`` to make this macro available.
- In CMake files, ``TIME_T_SIZE`` IDF build property will be set to the size of ``time_t``, in bytes. You may call ``idf_build_get_property(var TIME_T_SIZE)`` to get the value of this property into a CMake variable ``var``. See :ref:`build system API reference <cmake_buildsystem_api>` for more information about ``idf_build_get_property``.
Note that the size of ``time_t`` type also affects the sizes of other types, for example ``struct timeval``, ``struct stat``, ``struct utimbuf``.
API Reference API Reference
------------- -------------

View File

@ -64,8 +64,6 @@ Download ``crosstool-NG`` and build it:
.. include-build-file:: inc/scratch-build-code.inc .. include-build-file:: inc/scratch-build-code.inc
.. note:: To create a toolchain with support for 64-bit time_t, you need to remove the ``--enable-newlib-long-time_t`` option from the ``crosstool-NG/samples/xtensa-esp32-elf/crosstool.config`` file in 33 and 43 lines.
Build the toolchain:: Build the toolchain::
./ct-ng {IDF_TARGET_TOOLCHAIN_PREFIX} ./ct-ng {IDF_TARGET_TOOLCHAIN_PREFIX}

View File

@ -1396,7 +1396,6 @@ components/newlib/test/test_time.c
components/newlib/test_apps/app_test.py components/newlib/test_apps/app_test.py
components/newlib/test_apps/main/test_newlib_main.c components/newlib/test_apps/main/test_newlib_main.c
components/newlib/test_apps/main/test_stdatomic.c components/newlib/test_apps/main/test_stdatomic.c
components/newlib/time.c
components/nvs_flash/host_test/fixtures/test_fixtures.hpp components/nvs_flash/host_test/fixtures/test_fixtures.hpp
components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp
components/nvs_flash/include/nvs.h components/nvs_flash/include/nvs.h