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.
pull/8238/head
Ivan Grokhotkov 2022-01-06 18:02:09 +01:00
rodzic bbe8aabca0
commit d2b894862c
9 zmienionych plików z 71 dodań i 84 usunięć

Wyświetl plik

@ -209,6 +209,16 @@ if(CMAKE_C_COMPILER_ID MATCHES "LLVM")
list(APPEND compile_options "-fno-use-cxa-atexit")
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(C_COMPILE_OPTIONS "${c_compile_options}" APPEND)
idf_build_set_property(CXX_COMPILE_OPTIONS "${cxx_compile_options}" APPEND)

20
Kconfig
Wyświetl plik

@ -104,26 +104,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
default 0x000E if IDF_TARGET_ESP32H2_BETA_VERSION_2 # ESP32H2-TODO: IDF-3475
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"

Wyświetl plik

@ -57,6 +57,8 @@ else()
rom_linker_script("libgcc")
endif()
idf_build_get_property(time_t_size TIME_T_SIZE)
if(BOOTLOADER_BUILD)
if(target STREQUAL "esp32")
rom_linker_script("newlib-funcs")
@ -91,19 +93,20 @@ else() # Regular app build
rom_linker_script("syscalls")
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")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
# then all time functions from the ROM memory will not be linked.
# Instead, those functions can be used from the toolchain by ESP-IDF.
if(time_t_size EQUAL 4)
# The ROM functions listed in this linker script depend on sizeof(time_t).
# 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")
# Include in newlib nano from ROM only if SPIRAM cache workaround is disabled
# and sizeof(time_t) == 4
if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano")
endif()
endif()
endif()
@ -120,52 +123,48 @@ else() # Regular app build
rom_linker_script("newlib-data")
rom_linker_script("spiflash")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
# then all time functions from the ROM memory will not be linked.
# Instead, those functions can be used from the toolchain by ESP-IDF.
if(time_t_size EQUAL 4)
# The ROM functions listed in this linker script depend on sizeof(time_t).
# Since ROM for ESP32-S2 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")
if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano")
endif()
rom_linker_script("newlib-time")
endif()
# descirptors used by ROM code
target_sources(${COMPONENT_LIB} PRIVATE "esp32s2/usb_descriptors.c")
elseif(target STREQUAL "esp32s3")
rom_linker_script("newlib")
rom_linker_script("version")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
# then all time functions from the ROM memory will not be linked.
# Instead, those functions can be used from the toolchain by ESP-IDF.
if(time_t_size EQUAL 4)
# The ROM functions listed in this linker script depend on sizeof(time_t).
# Since ROM for ESP32-S3 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")
if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano")
endif()
rom_linker_script("newlib-time")
endif()
elseif(target STREQUAL "esp32c3")
rom_linker_script("newlib")
rom_linker_script("version")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
# If SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS option is defined
# then all time functions from the ROM memory will not be linked.
# Instead, those functions can be used from the toolchain by ESP-IDF.
if(time_t_size EQUAL 4)
# The ROM functions listed in this linker script depend on sizeof(time_t).
# Since ROM for ESP32-C3 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")
if(CONFIG_NEWLIB_NANO_FORMAT)
# nano formatting functions in ROM are also built for 32-bit time_t.
rom_linker_script("newlib-nano")
endif()
rom_linker_script("newlib-time")
endif()
if(CONFIG_ESP32C3_REV_MIN_3)
@ -176,10 +175,10 @@ else() # Regular app build
rom_linker_script("newlib")
rom_linker_script("version")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
if(CONFIG_NEWLIB_NANO_FORMAT)
rom_linker_script("newlib-nano")
endif()
if(CONFIG_NEWLIB_NANO_FORMAT AND time_t_size EQUAL 4)
# 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")
endif()
elseif(target STREQUAL "esp8684")
@ -187,10 +186,10 @@ else() # Regular app build
rom_linker_script("version")
rom_linker_script("mbedtls")
if(NOT CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS)
if(CONFIG_NEWLIB_NANO_FORMAT)
rom_linker_script("newlib-nano")
endif()
if(CONFIG_NEWLIB_NANO_FORMAT AND time_t_size EQUAL 4)
# 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")
endif()
endif()

Wyświetl plik

@ -1,4 +1,5 @@
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "unity.h"
#include "driver/adc.h"
@ -446,8 +447,7 @@ TEST_CASE("test posix_timers clock_... functions", "[newlib]")
test_posix_timers_clock();
}
#ifdef CONFIG_SDK_TOOLCHAIN_SUPPORTS_TIME_WIDE_64_BITS
#include <string.h>
#ifndef _USE_LONG_TIME_T
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 )

Wyświetl plik

@ -1,16 +1,8 @@
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// 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.
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <stdlib.h>
@ -37,12 +29,6 @@
#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
#define IMPL_NEWLIB_TIME_FUNCS 1
#endif

Wyświetl plik

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

Wyświetl plik

@ -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.
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
-------------

Wyświetl plik

@ -64,8 +64,6 @@ Download ``crosstool-NG`` and build it:
.. 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::
./ct-ng {IDF_TARGET_TOOLCHAIN_PREFIX}

Wyświetl plik

@ -1396,7 +1396,6 @@ components/newlib/test/test_time.c
components/newlib/test_apps/app_test.py
components/newlib/test_apps/main/test_newlib_main.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/nvs_page_test/main/nvs_page_test.cpp
components/nvs_flash/include/nvs.h